From a550aa66e2a66108d29f1d61d72897c740f3d8f4 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sun, 25 Jan 2026 18:49:22 -0500 Subject: [PATCH 01/13] feat: add V3 protocol support (Governance, Content Standards, SI, CLI) Add comprehensive V3 ADCP protocol support including: Server Framework: - Add GovernanceHandler for property list management - Add ContentStandardsHandler for content calibration - Add SponsoredIntelligenceHandler for conversational AI sponsorship - Add governance method stubs to all protocol handlers - Add MCP tool definitions for all V3 operations Client: - Add typed client methods for all V3 operations - Export all V3 types from adcp.types Protocol Adapters: - Add governance methods to protocol base class - Add governance implementations to MCP and A2A adapters CLI: - Add all V3 operations to command-line client: - Protocol Discovery: get_adcp_capabilities - Content Standards: 7 operations - Sponsored Intelligence: 4 operations - Governance: 5 operations Types: - Sync schemas with ADCP 2.6+ spec - Generate types for V3 domains Co-Authored-By: Claude Opus 4.5 --- schemas/cache/.hashes.json | 383 ++++---- schemas/cache/adagents.json | 18 +- .../artifact-webhook-payload.json | 79 ++ schemas/cache/content-standards/artifact.json | 351 +++++++ .../calibrate-content-request.json | 20 + .../calibrate-content-response.json | 89 ++ .../content-standards/content-standards.json | 68 ++ .../create-content-standards-request.json | 136 +++ .../create-content-standards-response.json | 60 ++ .../get-content-standards-request.json | 21 + .../get-content-standards-response.json | 51 ++ .../get-media-buy-artifacts-request.json | 77 ++ .../get-media-buy-artifacts-response.json | 160 ++++ .../list-content-standards-request.json | 36 + .../list-content-standards-response.json | 59 ++ .../update-content-standards-request.json | 136 +++ .../update-content-standards-response.json | 44 + .../validate-content-delivery-request.json | 87 ++ .../validate-content-delivery-response.json | 131 +++ schemas/cache/core/brand-manifest.json | 97 +- schemas/cache/core/creative-asset.json | 8 +- schemas/cache/core/creative-filters.json | 18 +- schemas/cache/core/media-buy-features.json | 23 + schemas/cache/core/offering.json | 150 +++ schemas/cache/core/product-allocation.json | 46 + schemas/cache/core/product-filters.json | 65 +- schemas/cache/core/promoted-offerings.json | 108 ++- schemas/cache/core/proposal.json | 72 ++ schemas/cache/core/reporting-webhook.json | 66 ++ schemas/cache/core/targeting.json | 59 +- schemas/cache/creative/asset-types/index.json | 8 +- schemas/cache/enums/channels.json | 47 +- schemas/cache/enums/creative-status.json | 4 +- schemas/cache/enums/geo-level.json | 12 + schemas/cache/enums/metro-system.json | 13 + schemas/cache/enums/postal-system.json | 17 + schemas/cache/enums/property-type.json | 13 +- schemas/cache/enums/standard-format-ids.json | 102 --- schemas/cache/extensions/index.json | 2 +- .../media-buy/create-media-buy-request.json | 144 +-- .../cache/media-buy/get-products-request.json | 6 +- .../media-buy/get-products-response.json | 7 + .../media-buy/list-creatives-response.json | 30 +- schemas/cache/media-buy/package-request.json | 8 +- schemas/cache/media-buy/package-update.json | 72 ++ .../media-buy/update-media-buy-request.json | 78 +- .../list-property-features-request.json | 26 - .../list-property-features-response.json | 22 - .../get-adcp-capabilities-request.json | 27 + .../get-adcp-capabilities-response.json | 390 ++++++++ schemas/cache/protocols/adcp-extension.json | 16 +- .../si-capabilities.json | 128 +++ .../si-get-offering-request.json | 35 + .../si-get-offering-response.json | 142 +++ .../sponsored-intelligence/si-identity.json | 101 ++ .../si-initiate-session-request.json | 43 + .../si-initiate-session-response.json | 48 + .../si-send-message-request.json | 50 + .../si-send-message-response.json | 113 +++ .../si-terminate-session-request.json | 64 ++ .../si-terminate-session-response.json | 70 ++ .../sponsored-intelligence/si-ui-element.json | 339 +++++++ scripts/generate_ergonomic_coercion.py | 22 +- src/adcp/ADCP_VERSION | 2 +- src/adcp/__init__.py | 4 - src/adcp/__main__.py | 90 ++ src/adcp/client.py | 865 ++++++++++++++++++ src/adcp/protocols/a2a.py | 84 ++ src/adcp/protocols/base.py | 101 ++ src/adcp/protocols/mcp.py | 84 ++ src/adcp/server/__init__.py | 49 + src/adcp/server/base.py | 366 ++++++++ src/adcp/server/content_standards.py | 369 ++++++++ src/adcp/server/governance.py | 351 +++++++ src/adcp/server/mcp_tools.py | 470 ++++++++++ src/adcp/server/proposal.py | 334 +++++++ src/adcp/server/sponsored_intelligence.py | 329 +++++++ src/adcp/types/__init__.py | 132 ++- src/adcp/types/_ergonomic.py | 72 +- src/adcp/types/_generated.py | 383 +++++++- src/adcp/types/aliases.py | 17 +- src/adcp/types/generated_poc/adagents.py | 385 ++++---- .../content_standards/__init__.py | 3 + .../content_standards/artifact.py | 208 +++++ .../artifact_webhook_payload.py | 64 ++ .../calibrate_content_request.py | 17 + .../calibrate_content_response.py | 74 ++ .../content_standards/content_standards.py | 66 ++ .../create_content_standards_request.py | 97 ++ .../create_content_standards_response.py | 52 ++ .../get_content_standards_request.py | 21 + .../get_content_standards_response.py | 43 + .../get_media_buy_artifacts_request.py | 64 ++ .../get_media_buy_artifacts_response.py | 117 +++ .../list_content_standards_request.py | 31 + .../list_content_standards_response.py | 48 + .../update_content_standards_request.py | 101 ++ .../update_content_standards_response.py | 40 + .../validate_content_delivery_request.py | 59 ++ .../validate_content_delivery_response.py | 85 ++ .../generated_poc/core/activation_key.py | 18 +- .../generated_poc/core/assets/audio_asset.py | 12 +- .../generated_poc/core/assets/css_asset.py | 6 +- .../generated_poc/core/assets/daast_asset.py | 38 +- .../generated_poc/core/assets/html_asset.py | 6 +- .../generated_poc/core/assets/image_asset.py | 14 +- .../core/assets/javascript_asset.py | 8 +- .../generated_poc/core/assets/text_asset.py | 6 +- .../generated_poc/core/assets/url_asset.py | 8 +- .../generated_poc/core/assets/vast_asset.py | 38 +- .../generated_poc/core/assets/video_asset.py | 16 +- .../core/assets/webhook_asset.py | 20 +- .../generated_poc/core/async_response_data.py | 6 +- .../generated_poc/core/brand_manifest.py | 181 ++-- .../generated_poc/core/brand_manifest_ref.py | 20 +- src/adcp/types/generated_poc/core/context.py | 4 +- .../generated_poc/core/creative_asset.py | 39 +- .../generated_poc/core/creative_assignment.py | 8 +- .../generated_poc/core/creative_filters.py | 46 +- .../generated_poc/core/creative_manifest.py | 6 +- .../generated_poc/core/creative_policy.py | 10 +- .../generated_poc/core/delivery_metrics.py | 66 +- .../types/generated_poc/core/deployment.py | 42 +- .../types/generated_poc/core/destination.py | 24 +- src/adcp/types/generated_poc/core/error.py | 14 +- src/adcp/types/generated_poc/core/ext.py | 4 +- src/adcp/types/generated_poc/core/format.py | 132 +-- .../types/generated_poc/core/format_id.py | 12 +- .../types/generated_poc/core/frequency_cap.py | 6 +- .../types/generated_poc/core/identifier.py | 6 +- .../generated_poc/core/mcp_webhook_payload.py | 22 +- .../types/generated_poc/core/measurement.py | 18 +- .../types/generated_poc/core/media_buy.py | 16 +- .../generated_poc/core/media_buy_features.py | 29 + src/adcp/types/generated_poc/core/offering.py | 80 ++ src/adcp/types/generated_poc/core/package.py | 18 +- .../core/performance_feedback.py | 38 +- .../types/generated_poc/core/placement.py | 10 +- .../generated_poc/core/pricing_option.py | 6 +- src/adcp/types/generated_poc/core/product.py | 42 +- .../generated_poc/core/product_allocation.py | 48 + .../generated_poc/core/product_filters.py | 110 ++- .../generated_poc/core/promoted_offerings.py | 67 +- .../generated_poc/core/promoted_products.py | 6 +- src/adcp/types/generated_poc/core/property.py | 20 +- .../types/generated_poc/core/property_id.py | 10 +- .../generated_poc/core/property_list_ref.py | 10 +- .../types/generated_poc/core/property_tag.py | 10 +- src/adcp/types/generated_poc/core/proposal.py | 64 ++ .../generated_poc/core/protocol_envelope.py | 18 +- .../core/publisher_property_selector.py | 28 +- .../core/push_notification_config.py | 12 +- .../core/reporting_capabilities.py | 18 +- .../generated_poc/core/reporting_webhook.py | 70 ++ src/adcp/types/generated_poc/core/response.py | 10 +- .../generated_poc/core/signal_filters.py | 12 +- .../types/generated_poc/core/start_timing.py | 8 +- .../types/generated_poc/core/sub_asset.py | 30 +- .../types/generated_poc/core/targeting.py | 77 +- .../creative/list_creative_formats_request.py | 42 +- .../list_creative_formats_response.py | 12 +- .../creative/preview_creative_request.py | 50 +- .../creative/preview_creative_response.py | 58 +- .../generated_poc/creative/preview_render.py | 52 +- .../types/generated_poc/enums/adcp_domain.py | 10 +- .../generated_poc/enums/asset_content_type.py | 28 +- .../types/generated_poc/enums/auth_scheme.py | 6 +- .../generated_poc/enums/available_metric.py | 20 +- .../types/generated_poc/enums/channels.py | 32 +- .../enums/co_branding_requirement.py | 8 +- .../generated_poc/enums/creative_action.py | 12 +- .../enums/creative_agent_capability.py | 10 +- .../enums/creative_sort_field.py | 14 +- .../generated_poc/enums/creative_status.py | 11 +- .../enums/daast_tracking_event.py | 24 +- .../generated_poc/enums/daast_version.py | 6 +- .../generated_poc/enums/delivery_type.py | 6 +- .../generated_poc/enums/dimension_unit.py | 10 +- .../types/generated_poc/enums/feed_format.py | 8 +- .../generated_poc/enums/feedback_source.py | 10 +- .../generated_poc/enums/format_category.py | 16 +- .../enums/format_id_parameter.py | 6 +- .../enums/frequency_cap_scope.py | 8 +- .../types/generated_poc/enums/geo_level.py | 14 + .../generated_poc/enums/history_entry_type.py | 6 +- .../types/generated_poc/enums/http_method.py | 6 +- .../generated_poc/enums/identifier_types.py | 40 +- .../enums/javascript_module_type.py | 8 +- .../enums/landing_page_requirement.py | 8 +- .../generated_poc/enums/markdown_flavor.py | 6 +- .../generated_poc/enums/media_buy_status.py | 10 +- .../types/generated_poc/enums/metric_type.py | 18 +- .../types/generated_poc/enums/metro_system.py | 15 + .../generated_poc/enums/notification_type.py | 10 +- src/adcp/types/generated_poc/enums/pacing.py | 8 +- .../generated_poc/enums/postal_system.py | 19 + .../enums/preview_output_format.py | 6 +- .../generated_poc/enums/pricing_model.py | 16 +- .../generated_poc/enums/property_type.py | 17 +- .../enums/publisher_identifier_types.py | 12 +- .../enums/reporting_frequency.py | 8 +- .../enums/signal_catalog_type.py | 8 +- .../generated_poc/enums/sort_direction.py | 6 +- .../enums/standard_format_ids.py | 45 - .../types/generated_poc/enums/task_status.py | 20 +- .../types/generated_poc/enums/task_type.py | 24 +- .../generated_poc/enums/update_frequency.py | 10 +- .../generated_poc/enums/url_asset_type.py | 8 +- .../generated_poc/enums/validation_mode.py | 6 +- .../enums/vast_tracking_event.py | 34 +- .../types/generated_poc/enums/vast_version.py | 12 +- .../enums/webhook_response_type.py | 10 +- .../enums/webhook_security_method.py | 8 +- .../extensions/extension_meta.py | 24 +- .../media_buy/build_creative_request.py | 10 +- .../media_buy/build_creative_response.py | 14 +- ...media_buy_async_response_input_required.py | 12 +- ...eate_media_buy_async_response_submitted.py | 4 +- ...create_media_buy_async_response_working.py | 12 +- .../media_buy/create_media_buy_request.py | 102 ++- .../media_buy/create_media_buy_response.py | 16 +- .../get_media_buy_delivery_request.py | 18 +- .../get_media_buy_delivery_response.py | 104 +-- ..._products_async_response_input_required.py | 14 +- .../get_products_async_response_submitted.py | 6 +- .../get_products_async_response_working.py | 10 +- .../media_buy/get_products_request.py | 19 +- .../media_buy/get_products_response.py | 18 +- .../list_authorized_properties_request.py | 8 +- .../list_authorized_properties_response.py | 18 +- .../list_creative_formats_request.py | 20 +- .../list_creative_formats_response.py | 12 +- .../media_buy/list_creatives_request.py | 48 +- .../media_buy/list_creatives_response.py | 111 ++- .../media_buy/package_request.py | 24 +- .../generated_poc/media_buy/package_update.py | 119 +++ .../provide_performance_feedback_request.py | 40 +- .../provide_performance_feedback_response.py | 14 +- ...creatives_async_response_input_required.py | 12 +- ...sync_creatives_async_response_submitted.py | 4 +- .../sync_creatives_async_response_working.py | 16 +- .../media_buy/sync_creatives_request.py | 16 +- .../media_buy/sync_creatives_response.py | 32 +- ...media_buy_async_response_input_required.py | 10 +- ...date_media_buy_async_response_submitted.py | 4 +- ...update_media_buy_async_response_working.py | 12 +- .../media_buy/update_media_buy_request.py | 152 +-- .../media_buy/update_media_buy_response.py | 16 +- .../pricing_options/cpc_option.py | 18 +- .../pricing_options/cpcv_option.py | 18 +- .../pricing_options/cpm_auction_option.py | 28 +- .../pricing_options/cpm_fixed_option.py | 18 +- .../pricing_options/cpp_option.py | 28 +- .../pricing_options/cpv_option.py | 26 +- .../pricing_options/flat_rate_option.py | 32 +- .../pricing_options/vcpm_auction_option.py | 28 +- .../pricing_options/vcpm_fixed_option.py | 18 +- .../property/base_property_source.py | 32 +- .../property/create_property_list_request.py | 10 +- .../property/create_property_list_response.py | 8 +- .../property/delete_property_list_request.py | 6 +- .../property/delete_property_list_response.py | 8 +- .../property/feature_requirement.py | 16 +- .../property/get_property_list_request.py | 12 +- .../property/get_property_list_response.py | 24 +- .../list_property_features_request.py | 25 - .../list_property_features_response.py | 24 - .../property/list_property_lists_request.py | 12 +- .../property/list_property_lists_response.py | 18 +- .../generated_poc/property/property_error.py | 22 +- .../property/property_feature.py | 10 +- .../property/property_feature_definition.py | 38 +- .../generated_poc/property/property_list.py | 24 +- .../property/property_list_changed_webhook.py | 24 +- .../property/property_list_filters.py | 18 +- .../property/update_property_list_request.py | 18 +- .../property/update_property_list_response.py | 6 +- .../types/generated_poc/protocol/__init__.py | 3 + .../protocol/get_adcp_capabilities_request.py | 34 + .../get_adcp_capabilities_response.py | 353 +++++++ .../generated_poc/protocols/adcp_extension.py | 31 +- .../signals/activate_signal_request.py | 8 +- .../signals/activate_signal_response.py | 14 +- .../signals/get_signals_request.py | 18 +- .../signals/get_signals_response.py | 32 +- .../sponsored_intelligence/__init__.py | 3 + .../sponsored_intelligence/si_capabilities.py | 102 +++ .../si_get_offering_request.py | 34 + .../si_get_offering_response.py | 100 ++ .../sponsored_intelligence/si_identity.py | 78 ++ .../si_initiate_session_request.py | 46 + .../si_initiate_session_response.py | 44 + .../si_send_message_request.py | 58 ++ .../si_send_message_response.py | 101 ++ .../si_terminate_session_request.py | 60 ++ .../si_terminate_session_response.py | 54 ++ .../sponsored_intelligence/si_ui_element.py | 30 + src/adcp/utils/format_assets.py | 10 +- tests/test_cli.py | 48 +- tests/test_server_framework.py | 532 +++++++++++ tests/test_type_aliases.py | 45 +- tests/test_type_coercion.py | 19 +- 302 files changed, 13838 insertions(+), 2853 deletions(-) create mode 100644 schemas/cache/content-standards/artifact-webhook-payload.json create mode 100644 schemas/cache/content-standards/artifact.json create mode 100644 schemas/cache/content-standards/calibrate-content-request.json create mode 100644 schemas/cache/content-standards/calibrate-content-response.json create mode 100644 schemas/cache/content-standards/content-standards.json create mode 100644 schemas/cache/content-standards/create-content-standards-request.json create mode 100644 schemas/cache/content-standards/create-content-standards-response.json create mode 100644 schemas/cache/content-standards/get-content-standards-request.json create mode 100644 schemas/cache/content-standards/get-content-standards-response.json create mode 100644 schemas/cache/content-standards/get-media-buy-artifacts-request.json create mode 100644 schemas/cache/content-standards/get-media-buy-artifacts-response.json create mode 100644 schemas/cache/content-standards/list-content-standards-request.json create mode 100644 schemas/cache/content-standards/list-content-standards-response.json create mode 100644 schemas/cache/content-standards/update-content-standards-request.json create mode 100644 schemas/cache/content-standards/update-content-standards-response.json create mode 100644 schemas/cache/content-standards/validate-content-delivery-request.json create mode 100644 schemas/cache/content-standards/validate-content-delivery-response.json create mode 100644 schemas/cache/core/media-buy-features.json create mode 100644 schemas/cache/core/offering.json create mode 100644 schemas/cache/core/product-allocation.json create mode 100644 schemas/cache/core/proposal.json create mode 100644 schemas/cache/core/reporting-webhook.json create mode 100644 schemas/cache/enums/geo-level.json create mode 100644 schemas/cache/enums/metro-system.json create mode 100644 schemas/cache/enums/postal-system.json delete mode 100644 schemas/cache/enums/standard-format-ids.json create mode 100644 schemas/cache/media-buy/package-update.json delete mode 100644 schemas/cache/property/list-property-features-request.json delete mode 100644 schemas/cache/property/list-property-features-response.json create mode 100644 schemas/cache/protocol/get-adcp-capabilities-request.json create mode 100644 schemas/cache/protocol/get-adcp-capabilities-response.json create mode 100644 schemas/cache/sponsored-intelligence/si-capabilities.json create mode 100644 schemas/cache/sponsored-intelligence/si-get-offering-request.json create mode 100644 schemas/cache/sponsored-intelligence/si-get-offering-response.json create mode 100644 schemas/cache/sponsored-intelligence/si-identity.json create mode 100644 schemas/cache/sponsored-intelligence/si-initiate-session-request.json create mode 100644 schemas/cache/sponsored-intelligence/si-initiate-session-response.json create mode 100644 schemas/cache/sponsored-intelligence/si-send-message-request.json create mode 100644 schemas/cache/sponsored-intelligence/si-send-message-response.json create mode 100644 schemas/cache/sponsored-intelligence/si-terminate-session-request.json create mode 100644 schemas/cache/sponsored-intelligence/si-terminate-session-response.json create mode 100644 schemas/cache/sponsored-intelligence/si-ui-element.json create mode 100644 src/adcp/server/__init__.py create mode 100644 src/adcp/server/base.py create mode 100644 src/adcp/server/content_standards.py create mode 100644 src/adcp/server/governance.py create mode 100644 src/adcp/server/mcp_tools.py create mode 100644 src/adcp/server/proposal.py create mode 100644 src/adcp/server/sponsored_intelligence.py create mode 100644 src/adcp/types/generated_poc/content_standards/__init__.py create mode 100644 src/adcp/types/generated_poc/content_standards/artifact.py create mode 100644 src/adcp/types/generated_poc/content_standards/artifact_webhook_payload.py create mode 100644 src/adcp/types/generated_poc/content_standards/calibrate_content_request.py create mode 100644 src/adcp/types/generated_poc/content_standards/calibrate_content_response.py create mode 100644 src/adcp/types/generated_poc/content_standards/content_standards.py create mode 100644 src/adcp/types/generated_poc/content_standards/create_content_standards_request.py create mode 100644 src/adcp/types/generated_poc/content_standards/create_content_standards_response.py create mode 100644 src/adcp/types/generated_poc/content_standards/get_content_standards_request.py create mode 100644 src/adcp/types/generated_poc/content_standards/get_content_standards_response.py create mode 100644 src/adcp/types/generated_poc/content_standards/get_media_buy_artifacts_request.py create mode 100644 src/adcp/types/generated_poc/content_standards/get_media_buy_artifacts_response.py create mode 100644 src/adcp/types/generated_poc/content_standards/list_content_standards_request.py create mode 100644 src/adcp/types/generated_poc/content_standards/list_content_standards_response.py create mode 100644 src/adcp/types/generated_poc/content_standards/update_content_standards_request.py create mode 100644 src/adcp/types/generated_poc/content_standards/update_content_standards_response.py create mode 100644 src/adcp/types/generated_poc/content_standards/validate_content_delivery_request.py create mode 100644 src/adcp/types/generated_poc/content_standards/validate_content_delivery_response.py create mode 100644 src/adcp/types/generated_poc/core/media_buy_features.py create mode 100644 src/adcp/types/generated_poc/core/offering.py create mode 100644 src/adcp/types/generated_poc/core/product_allocation.py create mode 100644 src/adcp/types/generated_poc/core/proposal.py create mode 100644 src/adcp/types/generated_poc/core/reporting_webhook.py create mode 100644 src/adcp/types/generated_poc/enums/geo_level.py create mode 100644 src/adcp/types/generated_poc/enums/metro_system.py create mode 100644 src/adcp/types/generated_poc/enums/postal_system.py delete mode 100644 src/adcp/types/generated_poc/enums/standard_format_ids.py create mode 100644 src/adcp/types/generated_poc/media_buy/package_update.py delete mode 100644 src/adcp/types/generated_poc/property/list_property_features_request.py delete mode 100644 src/adcp/types/generated_poc/property/list_property_features_response.py create mode 100644 src/adcp/types/generated_poc/protocol/__init__.py create mode 100644 src/adcp/types/generated_poc/protocol/get_adcp_capabilities_request.py create mode 100644 src/adcp/types/generated_poc/protocol/get_adcp_capabilities_response.py create mode 100644 src/adcp/types/generated_poc/sponsored_intelligence/__init__.py create mode 100644 src/adcp/types/generated_poc/sponsored_intelligence/si_capabilities.py create mode 100644 src/adcp/types/generated_poc/sponsored_intelligence/si_get_offering_request.py create mode 100644 src/adcp/types/generated_poc/sponsored_intelligence/si_get_offering_response.py create mode 100644 src/adcp/types/generated_poc/sponsored_intelligence/si_identity.py create mode 100644 src/adcp/types/generated_poc/sponsored_intelligence/si_initiate_session_request.py create mode 100644 src/adcp/types/generated_poc/sponsored_intelligence/si_initiate_session_response.py create mode 100644 src/adcp/types/generated_poc/sponsored_intelligence/si_send_message_request.py create mode 100644 src/adcp/types/generated_poc/sponsored_intelligence/si_send_message_response.py create mode 100644 src/adcp/types/generated_poc/sponsored_intelligence/si_terminate_session_request.py create mode 100644 src/adcp/types/generated_poc/sponsored_intelligence/si_terminate_session_response.py create mode 100644 src/adcp/types/generated_poc/sponsored_intelligence/si_ui_element.py create mode 100644 tests/test_server_framework.py diff --git a/schemas/cache/.hashes.json b/schemas/cache/.hashes.json index c92198b1..3207e58c 100644 --- a/schemas/cache/.hashes.json +++ b/schemas/cache/.hashes.json @@ -1,179 +1,208 @@ { - "https://adcontextprotocol.org/schemas/2.6.0/index.json": "1537f09a2322b856d4ba9d8a3d6ad53410001aeaadd0787d2f18108114410d37", - "https://adcontextprotocol.org/schemas/2.6.0/adagents.json": "3f6f73cdc071a70029c360335e2172a36ad80873bcfa76f9e3222cbcfd81674e", - "https://adcontextprotocol.org/schemas/2.6.0/core/activation-key.json": "bd518951d02618c71fbb7b986612e8eb407ff1e42e56e6425ff72fe62de6e398", - "https://adcontextprotocol.org/schemas/2.6.0/core/assets/audio-asset.json": "8f58b0eaab323f37148586ca6c6053c3837beb1f4e11bd90643d65493906fd9b", - "https://adcontextprotocol.org/schemas/2.6.0/core/assets/css-asset.json": "58b4d0e37c5c50de3aa0634e68782cb980243972effdbbbb031c9fed7909fcd6", - "https://adcontextprotocol.org/schemas/2.6.0/core/assets/daast-asset.json": "18f64de4f4364f2b088553022dde888e1bc6ae901c2aba7a1b92a5077a9953e5", - "https://adcontextprotocol.org/schemas/2.6.0/core/assets/html-asset.json": "b37af64a11db31323ae31507eb777db79faf3d1c3b66cefb8dbf464f6b95baf3", - "https://adcontextprotocol.org/schemas/2.6.0/core/assets/image-asset.json": "9c47dc5885925dada5edfe8fffa14b70f95d97f642d0273b6905cb3e080db96e", - "https://adcontextprotocol.org/schemas/2.6.0/core/assets/javascript-asset.json": "3ad5e2a3c9819e6e555a2963aa5bf3e027fc72510638e6d2d541142b6682fd75", - "https://adcontextprotocol.org/schemas/2.6.0/core/assets/text-asset.json": "c8fd0ccf60e36f96051ed39d29df5ad740af8bce2cf78b15586d2f1e9802d628", - "https://adcontextprotocol.org/schemas/2.6.0/core/assets/url-asset.json": "2ea5873ce10b2fa3c9974b336567ddf3f1d268845964dcbd1cb0491360ec41f8", - "https://adcontextprotocol.org/schemas/2.6.0/core/assets/vast-asset.json": "6afb68b10d96efea99e5df28636f26c12189660c73e3afd03b4b2434d87192b5", - "https://adcontextprotocol.org/schemas/2.6.0/core/assets/video-asset.json": "335d3757fd7e754915b36cb663ea512c253cd91f2300a31cc0f165147c5c482b", - "https://adcontextprotocol.org/schemas/2.6.0/core/assets/webhook-asset.json": "c2b54eaad6c73c993056f98640b1fefa10600e25d33db47b4c6950ea855f7bec", - "https://adcontextprotocol.org/schemas/2.6.0/core/async-response-data.json": "0504ab3c32e4c595fc8c08f6959ab7888d0418e0a3c529c6db54bfc3ec725958", - "https://adcontextprotocol.org/schemas/2.6.0/core/brand-manifest-ref.json": "b42d89abb6bbc3d94f778e4ca50db2afbc44abdc323ff6d023b0991bcf5c636d", - "https://adcontextprotocol.org/schemas/2.6.0/core/brand-manifest.json": "84d9894ee5ffa030faae0f1ef8ded063672646b9d2d93a3f95274e9b4d0d7e8f", - "https://adcontextprotocol.org/schemas/2.6.0/core/context.json": "c667cb6656a09b519e0149894c71892dc0b41058286330a7abec1c6be06d1dd5", - "https://adcontextprotocol.org/schemas/2.6.0/core/creative-asset.json": "54796fa16fdab4e27292a3046927f3fa4e3c0a31100d0193e5a9037ba325d7b8", - "https://adcontextprotocol.org/schemas/2.6.0/core/creative-assignment.json": "c974290891741554ed6cf52e90f8cd849ca42dc93945f93a0e1131db184f1dd3", - "https://adcontextprotocol.org/schemas/2.6.0/core/creative-filters.json": "2561da12331c8fe8fbc5b51a0548c63bea0dcbf8e6a4ef33e750177588f7bfd0", - "https://adcontextprotocol.org/schemas/2.6.0/core/creative-manifest.json": "5b1741e6c1f28afdc7809ab4e0b46e7e0f60c8c6fb60f4180c0137f62f424da5", - "https://adcontextprotocol.org/schemas/2.6.0/core/creative-policy.json": "3d21944d2d8cb3d8547ab1ab4e8039126ed59c927769390b6e88a37741a95c3c", - "https://adcontextprotocol.org/schemas/2.6.0/core/delivery-metrics.json": "d1f66f1e536857c3636ac1bc0f5d3cf4566a3d291489e2e957e857379dff5f20", - "https://adcontextprotocol.org/schemas/2.6.0/core/deployment.json": "abd117816662f22d2ca04e9d59e3ecf3a4d89e67cf00c42eb208d3e00b85da99", - "https://adcontextprotocol.org/schemas/2.6.0/core/destination.json": "9561298e4b57b864e3db61466d7779dfd504c5f0e4c7a57184b4dc4de802e08b", - "https://adcontextprotocol.org/schemas/2.6.0/core/error.json": "9ce9217be88ac6f84b26b93438ea5e79c5e57b3cf9ad3f7008977d751aa12111", - "https://adcontextprotocol.org/schemas/2.6.0/core/ext.json": "5f7140fa267fd56e02547bf89e13cbb7c9ba54d2cd763de4f29f09e50896f952", - "https://adcontextprotocol.org/schemas/2.6.0/core/format-id.json": "d9a14c1a435444d54c9f9367ae9c8c4e6587cb05f1548e98df3a003bc3aaf8bc", - "https://adcontextprotocol.org/schemas/2.6.0/core/format.json": "9031bcb6669c5bb78692f50fa16641ccd99fd314e566275ef012468b2daca587", - "https://adcontextprotocol.org/schemas/2.6.0/core/frequency-cap.json": "6a089fbfdbcdeb15f0f51341ddee9eb75e451ac03324b75bf3d6eb769f5964a1", - "https://adcontextprotocol.org/schemas/2.6.0/core/identifier.json": "0ab83432a7e5a4cf006e8e66e3daed37bb3762ced5e9c2bedf38a2f48864f98d", - "https://adcontextprotocol.org/schemas/2.6.0/core/mcp-webhook-payload.json": "b70c73f858af7128459f5cec9ae6eca8cca7201c0b0c5390622de9626abf243e", - "https://adcontextprotocol.org/schemas/2.6.0/core/measurement.json": "e69b4089087d788015d031db446ac96f338e1c1d404d26efc5e3d2333252552c", - "https://adcontextprotocol.org/schemas/2.6.0/core/media-buy.json": "d63e59bb894cfc0229118b1c20165b10755016ac24042d3d3d0ef268947ce482", - "https://adcontextprotocol.org/schemas/2.6.0/core/package.json": "3e95d5fc435f2a4ed9a68a9e4c8f2c02449669b0a770d41ffea91a6f91e4adb5", - "https://adcontextprotocol.org/schemas/2.6.0/core/performance-feedback.json": "499617d218e4ef538db7fabdc274f27bee659acc8f40c942d1decd093f78c6c9", - "https://adcontextprotocol.org/schemas/2.6.0/core/placement.json": "223fc39b7f5c4c39c79b871322130deb71e66675329d099769302b699a84dde4", - "https://adcontextprotocol.org/schemas/2.6.0/core/pricing-option.json": "971e4143584c5dc230d01931965f0560c4622c30af0ac596b13c00c7b3a947f8", - "https://adcontextprotocol.org/schemas/2.6.0/core/product-filters.json": "e7ed65699713c48a9a08edc3a183582365217cd7bcac3019795e81d432dcf22b", - "https://adcontextprotocol.org/schemas/2.6.0/core/product.json": "3366b26bdd6af8f6029a736c90097b0326d6cd92b3dc4b34fc0645a1364c6231", - "https://adcontextprotocol.org/schemas/2.6.0/core/promoted-offerings.json": "89904b5f4ac756cbb1344024a9962ef0e7dbfa32c6fac59379cd2e5876ae96a1", - "https://adcontextprotocol.org/schemas/2.6.0/core/promoted-products.json": "2e709fc90b776ece5907503ae83ca79af14dc0cc240a41782ddd9421aa13426f", - "https://adcontextprotocol.org/schemas/2.6.0/core/property-id.json": "875cc214bd58ddd8d480a7a5c76776f07e7e834daed4dc2a099fbceb973bdb97", - "https://adcontextprotocol.org/schemas/2.6.0/core/property-list-ref.json": "fb08094a2e7de7840303bc62a31777109d810c2838be2040fd411fb36568556d", - "https://adcontextprotocol.org/schemas/2.6.0/core/property-tag.json": "1a8a753226b02dbd359fb33abefb97dbdc13fd88b8eecf7321d5dd6d2942e6fe", - "https://adcontextprotocol.org/schemas/2.6.0/core/property.json": "a7d1be9f0813386f0061174810170bcc64731c06e9e8e436fd888f880c8edd3f", - "https://adcontextprotocol.org/schemas/2.6.0/core/protocol-envelope.json": "9a70425bdb28bbd69cf103f0826be514ba418f8186e244c22f6e0b5c2f966383", - "https://adcontextprotocol.org/schemas/2.6.0/core/publisher-property-selector.json": "a68ee6ebd20dc2f2195bce885d33785f91d325de48aee3316ead326b6cfc1289", - "https://adcontextprotocol.org/schemas/2.6.0/core/push-notification-config.json": "f43cac5b538808162bf51a49853a288f3d877dc29aba8cba71579a2d681d1d89", - "https://adcontextprotocol.org/schemas/2.6.0/core/reporting-capabilities.json": "e54e47a846197790b4d79e1d9ef978b13f4743f370d7562425e3b192b510b47f", - "https://adcontextprotocol.org/schemas/2.6.0/core/response.json": "91ea9185f3b317a5b1db21335e3662b98fd4266336ec2eba3dcdff7928881c48", - "https://adcontextprotocol.org/schemas/2.6.0/core/signal-filters.json": "2955477372ae338762a0f0af9f8af0f5e4deb183cdb4c486292d879e36f243bd", - "https://adcontextprotocol.org/schemas/2.6.0/core/start-timing.json": "64ff8e6fae2b1cf490c2d274f13f66813b0c1b8e6ce051bd4c6adbfdf45c5488", - "https://adcontextprotocol.org/schemas/2.6.0/core/sub-asset.json": "62cd6b334bb246504c927d7ef3e60b5d5624ae8d810fedb6301be87f710d3573", - "https://adcontextprotocol.org/schemas/2.6.0/core/targeting.json": "af891f2c882f3975e4a4c2fd3d2e04796fa7a401f19dbc6e39f6a00308a6dd01", - "https://adcontextprotocol.org/schemas/2.6.0/creative/asset-types/index.json": "389b7ff1ccd02d78a27e78a66dc05f9349a4213adf0fa022ac48d11ac1d61fbd", - "https://adcontextprotocol.org/schemas/2.6.0/creative/list-creative-formats-request.json": "f45d84c60e795a69cd51bccea0c8f4a8aa265ae219d7207f411bf1a0342ace7f", - "https://adcontextprotocol.org/schemas/2.6.0/creative/list-creative-formats-response.json": "a10637f93ab28ac03b78b8e5b5b8e129554ad907331695a766670b1d854d5fc2", - "https://adcontextprotocol.org/schemas/2.6.0/creative/preview-creative-request.json": "4d1cda6561ce2ff645724076f10b70ff7b1e3b17655e660b12efdbffa6852584", - "https://adcontextprotocol.org/schemas/2.6.0/creative/preview-creative-response.json": "1e7175be27ad98eb685e53ab6595796bad0950ea5425c4b8da45bfe20a9986b8", - "https://adcontextprotocol.org/schemas/2.6.0/creative/preview-render.json": "b40d4e01eeb98942db2b9bf4802b78f6596295f8c7dbf0c3bac90b3e8bd4ec23", - "https://adcontextprotocol.org/schemas/2.6.0/enums/adcp-domain.json": "ebcdc01f4c00aa50b156abc59d7d9f14674b01ccf935d8bf863ae5c517171b63", - "https://adcontextprotocol.org/schemas/2.6.0/enums/asset-content-type.json": "a62ab210987be79ca430e0b40ddf91ae65db2bf83465470515d5c263f1dac2bb", - "https://adcontextprotocol.org/schemas/2.6.0/enums/auth-scheme.json": "1a8e9be46cce2432d7f58be1888d140f9783f73bb97a20c10dfcf9070161d2f4", - "https://adcontextprotocol.org/schemas/2.6.0/enums/available-metric.json": "b9beb1e79930ddd6d0f32ce41feee89ca10615fc61291d1f2227142fbfd47ddf", - "https://adcontextprotocol.org/schemas/2.6.0/enums/channels.json": "a77c405af340905ff47aaafdb766f38c0f041ed2e2e01970954edbe7282a0fa3", - "https://adcontextprotocol.org/schemas/2.6.0/enums/co-branding-requirement.json": "9340337b34e18abc0c2a73eed9ca1932deab734c055730e332c491daf8957f11", - "https://adcontextprotocol.org/schemas/2.6.0/enums/creative-action.json": "fc5c1ebbffd46c7a408aaa59e89c63c81bb61b5ecbbc032a60d93246403d4346", - "https://adcontextprotocol.org/schemas/2.6.0/enums/creative-agent-capability.json": "9b40c5c8d696a0b53ea22fade765e1d1aaf8ce161d575cf84b5bdf1b1448cb6d", - "https://adcontextprotocol.org/schemas/2.6.0/enums/creative-sort-field.json": "95cbb824bc189f9d5b4e6082d7f6ca003a43ca2da643725e60a173ea4f4c6081", - "https://adcontextprotocol.org/schemas/2.6.0/enums/creative-status.json": "b14c4aa8cfa3ea2fc9fb62763ae5dc482db9fb167eb33808438b0bfe8345cd3d", - "https://adcontextprotocol.org/schemas/2.6.0/enums/daast-tracking-event.json": "de04a339007b22b71b0d775df05aeaab052dc7fffbcab1655d8598e293035d70", - "https://adcontextprotocol.org/schemas/2.6.0/enums/daast-version.json": "32f5fcf31e87627d7f3f96e50232ff62557263534a3a476e298cf4c7c3695f73", - "https://adcontextprotocol.org/schemas/2.6.0/enums/delivery-type.json": "f7e6f2f9d63dba975614d37be5dc45cb6829ed77ad9732b7b95dc845e735cb66", - "https://adcontextprotocol.org/schemas/2.6.0/enums/dimension-unit.json": "db0027875a27109507d4a7ed9dc6e050c9a2a6d96433fa98ccce8ff1f37b1d20", - "https://adcontextprotocol.org/schemas/2.6.0/enums/feed-format.json": "67298ba035f9b095c6b4ae94fd318238a4d4f6edab175947f96f989b0db65ffd", - "https://adcontextprotocol.org/schemas/2.6.0/enums/feedback-source.json": "1f1059f2f2a64a6bcfedc8fc653f2def8b1b6cd544923ddd2ca697dc7f89526c", - "https://adcontextprotocol.org/schemas/2.6.0/enums/format-category.json": "587516d32b0455e0b44c86dbb01a3724033393899947b024302193ba0e4974ad", - "https://adcontextprotocol.org/schemas/2.6.0/enums/format-id-parameter.json": "ded3a4d0231e30709548086156867a3f27752d793fd1f504c62e15e193a9ba96", - "https://adcontextprotocol.org/schemas/2.6.0/enums/frequency-cap-scope.json": "4518e7b779353f0403a6e8ab7b8da5d1c775c745a8399d1e118fb0ac15893b9f", - "https://adcontextprotocol.org/schemas/2.6.0/enums/history-entry-type.json": "b46fee7bcd5f978347a5458b0209c176aa81a8be5bd06a23c4e6ac8574fc2c59", - "https://adcontextprotocol.org/schemas/2.6.0/enums/http-method.json": "b2f7e41876231efdc447ea58fa57a8e45933f6334aa2fcc17984f8007c6ba04f", - "https://adcontextprotocol.org/schemas/2.6.0/enums/identifier-types.json": "ce71e52ed324f17d51c57e8cae4976777a4a24f2701329e7808857676ca0e360", - "https://adcontextprotocol.org/schemas/2.6.0/enums/javascript-module-type.json": "227746528d3c02aeb31435b2dc7acc0502506313802ecec3a5022f4cd3cbf226", - "https://adcontextprotocol.org/schemas/2.6.0/enums/landing-page-requirement.json": "1cd39e922ce52a8710e0ba2db1430736c37ced565eca69e7a949f25b1a98f47a", - "https://adcontextprotocol.org/schemas/2.6.0/enums/markdown-flavor.json": "872bc5111d2397fc18c897b7f81c339be6604dbb3f88137ff278489d8ca89d60", - "https://adcontextprotocol.org/schemas/2.6.0/enums/media-buy-status.json": "7add3ed9ada1f4e867f1fab201d9be2f9a99eac110777f5a1932e16082f8358b", - "https://adcontextprotocol.org/schemas/2.6.0/enums/metric-type.json": "cab969ccc0fc057922cd89152977bbc9880370cf8a07aa4c7f7bee7a24ecb381", - "https://adcontextprotocol.org/schemas/2.6.0/enums/notification-type.json": "6dd5e835219c69ae289bb0261370a36b54e0b616cf9a7e2dfa88bd85e4761bd1", - "https://adcontextprotocol.org/schemas/2.6.0/enums/pacing.json": "730b6ff468ac9ec536b41fc93c6abc60d87acbbdc8cb67db9b8bc866acf89507", - "https://adcontextprotocol.org/schemas/2.6.0/enums/preview-output-format.json": "dcf5cad1d6b0878f92c981719786816ee9ce9c94d0ff28946920b9db3c168d94", - "https://adcontextprotocol.org/schemas/2.6.0/enums/pricing-model.json": "4db3c61a96392a200aef52fc6b0c87095c18855e150695b66a45d92e33c2de73", - "https://adcontextprotocol.org/schemas/2.6.0/enums/property-type.json": "4fafa162288a4ebf2dfcfe15d6d51c7c2886fa61873d0723525ea9d9aafa4911", - "https://adcontextprotocol.org/schemas/2.6.0/enums/publisher-identifier-types.json": "31d5d719846f3c697bef9581e849627099e13b6fe71663debcea04012b784b00", - "https://adcontextprotocol.org/schemas/2.6.0/enums/reporting-frequency.json": "7b8ec2d2f6e6bb68fccc782b1d05de274cf90c5f1873fc5982d39b3427817626", - "https://adcontextprotocol.org/schemas/2.6.0/enums/signal-catalog-type.json": "40692e383cb134b5e5d0159255ebc4ec426a65beeea55ebec1ab462525e6b314", - "https://adcontextprotocol.org/schemas/2.6.0/enums/sort-direction.json": "f1d72dfbdcff421cb81349b1c5209b5f6747b0d3a124f93ead7a325ba758309b", - "https://adcontextprotocol.org/schemas/2.6.0/enums/standard-format-ids.json": "9fd7f60107a25be0a66bd57f8bb3aa82122f554ab185686a7eccbc753749c40d", - "https://adcontextprotocol.org/schemas/2.6.0/enums/task-status.json": "7baa27e10078fec73b64b223170c39f3db89d818a82ad41ca9f02b6fd5c4b77b", - "https://adcontextprotocol.org/schemas/2.6.0/enums/task-type.json": "3f0f97cfa6e8c11d3f352d4c6bdc67b1cb53ff03ff49d8ff3b9a1464af0df9ac", - "https://adcontextprotocol.org/schemas/2.6.0/enums/update-frequency.json": "ada6745eb5c7edaebec2693478da6fd93fb807c48413332132b1d7df97e31688", - "https://adcontextprotocol.org/schemas/2.6.0/enums/url-asset-type.json": "39e064861db8b50e41bef2dfa373f8309a2a14b27e65a93a6c3bb369d6f795f4", - "https://adcontextprotocol.org/schemas/2.6.0/enums/validation-mode.json": "437dc25f290358d95ff5352fc26bdda5a992dfe8f04a191e16b2106e3d21071e", - "https://adcontextprotocol.org/schemas/2.6.0/enums/vast-tracking-event.json": "f275ebe947d5609175550935989891819cc19e6c3b64a631a8b0927a9144b715", - "https://adcontextprotocol.org/schemas/2.6.0/enums/vast-version.json": "5734bcc344af47e3ad4dcf68f155538614babaec7788326f5d82cec3129559ec", - "https://adcontextprotocol.org/schemas/2.6.0/enums/webhook-response-type.json": "d81db53c78b4ae5ff32287746903ab9bbaf848859ef222dd9ed8d7c0ed17ed60", - "https://adcontextprotocol.org/schemas/2.6.0/enums/webhook-security-method.json": "f74d763f720823948e5ade72a3a139e95675247e25a2671cfea6643d9a8f4872", - "https://adcontextprotocol.org/schemas/2.6.0/extensions/extension-meta.json": "1b4fc8ef344b08789514f86c2fa5d265cd47528e27b619aa5015ddaebd33075e", - "https://adcontextprotocol.org/schemas/2.6.0/extensions/index.json": "294f00ad72c90fb79810757cf23c1a770316a8fb9ef956da4a69483d5e5325ae", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/build-creative-request.json": "2633ac57f3a70c5ff82c2c240ca8066191d1778164c1415c4411593c9a7d4086", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/build-creative-response.json": "1b57abef495014331fe2e50a337048034c3b95d4a4e57c862664e40ce8a198d0", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/create-media-buy-async-response-input-required.json": "74c43004e366b5af309ebf2fcf2d757b181efe7124a09e36b09ea85a92fb3a86", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/create-media-buy-async-response-submitted.json": "c61193abebcf766bf587ae01c46303a7387c8fcdf79c1b5efd246535662d96a3", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/create-media-buy-async-response-working.json": "c61630024e3803e09840f059ff95c257b247e0fda5c1a33dca5bea5fd1bfc890", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/create-media-buy-request.json": "01740da777f9468703c2856f8f76d3ed4beca21b2782a6e4109c73fe51d4bb4d", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/create-media-buy-response.json": "f9778d117dcd2db8705b01c511ee612231006102e5c1d9379b229bddd9fd439c", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-media-buy-delivery-request.json": "0da39fd5d7220b501694ff8e8950e254479e336bbe6ad4c0fc6e78a82941f63d", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-media-buy-delivery-response.json": "7a135f8998c29800959a39b7b8e929a80e907654d08a34e22becd9d7dba5f2c8", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-products-async-response-input-required.json": "00630687e7f8876e0fa14c14ad7f4989ce244b147cafdffe3089c62a062927eb", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-products-async-response-submitted.json": "1a02a09edfb86e4cbd677d161b1ee208427593b4e85c68930e565cf2b849dd30", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-products-async-response-working.json": "eab7913469420a43c9461e20bfe6bd057a139d49cfae08b59b71d7445cf0dab8", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-products-request.json": "7c690fac3a26d4b6211661429a01edaa55ccb3c7b1eff6e7808ef91cbf271443", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/get-products-response.json": "501bf6f8aaaa18f7efe10a865612d56167e2b56196bd6daae29e59c781607f22", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/list-authorized-properties-request.json": "b13aa3eddcb4cb3e5efe64dca2dd520d5e83dfaa542587b5d88c360ddfa56178", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/list-authorized-properties-response.json": "11520ba350e4af718dbdb4f0122f3a4d9e278a460b4eeaffad265772446d43b3", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/list-creative-formats-request.json": "91990929c6c46a1d232bfb96a06d9ea9984b30de66d73d67a57744b7c3e90ad1", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/list-creative-formats-response.json": "9237034591d0c325367d9530ae843f809a7927424a9c3ffca42a96b3826e3803", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/list-creatives-request.json": "0788f951ff430c8cea3a012bd7c4ad64568385fa8f3ebf31e5930bad55702e09", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/list-creatives-response.json": "4ce8932d0a9d03a2d3268e486367f1b6e9bf8b8e4811fe54cb8b0cfd1ed9943a", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/package-request.json": "b9670c860d2b3ee6e09bfd5d246b33f75ce8c36fd407a936edf0773be6533d3e", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/provide-performance-feedback-request.json": "a75a015151b0bb2dea2eb5a38b4277b5ce610c6f73a6e36985742d1ca155d905", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/provide-performance-feedback-response.json": "221b7abdf0ba2765e498cc26d3f0bd91457e38a0c721d845a07465f87340bbf1", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/sync-creatives-async-response-input-required.json": "e47eb69105a4c390b37a15c5097343d8b8a7491342e721bc7ddcab780de241de", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/sync-creatives-async-response-submitted.json": "6a715ca5966419ac98eb709a78a2f6790fe573ac487190316935a72c8c533576", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/sync-creatives-async-response-working.json": "ae2d75d062fd633e0661ef6fa10f712b1a88ddea237f4df8178b18110eece5f6", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/sync-creatives-request.json": "972112985ae62cfc4f15e7083ed0c1992afa4bc5c377abaa063e5e02f2a27de9", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/sync-creatives-response.json": "fba9d521d1a57ee8839a80f5cf7ac38bc0c5b4b719aff50d6fbe9074a50c95a7", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/update-media-buy-async-response-input-required.json": "ec4b8fedaeba9a5343a858b540a390703381f93f13ba6842cdf334f3d1ce300f", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/update-media-buy-async-response-submitted.json": "61c4b236551201ce1f2af4be0f91b75dc3ab51731e282e3c9cd6cb74011b72de", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/update-media-buy-async-response-working.json": "bda5f4df3faf1b0468ac2492b965bd20828a9fafa1c891b3673e68596c5d342e", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/update-media-buy-request.json": "495f250df3f3fec67bcb8561ea84e55acddf2b376ce23d30778d2d391692a9d3", - "https://adcontextprotocol.org/schemas/2.6.0/media-buy/update-media-buy-response.json": "19c8537f9f734363820f52a96fc815344fb9cb70eb8e3e88c73296297ffa5a68", - "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/cpc-option.json": "34c1a9b76b94065d48c9a5d45534ce81f088c7c3b385f783a8afca8b73da24c9", - "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/cpcv-option.json": "ea756831fda6ab8dcad3a1e1d956fe96733e11005926e871c5272050fb0f11fb", - "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/cpm-auction-option.json": "fdc3f30491967fe78586cfd69a1042164b0abf6e87d9c606e2090c17b828e306", - "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/cpm-fixed-option.json": "0dad3b1aa255a79fba2256b40641420293865ccb93345841207a717e06f9accd", - "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/cpp-option.json": "9efebfce87458ae552ad5bc2a0923bfb10d1e55d6c1709312e009c2655209fce", - "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/cpv-option.json": "732165490aa7cba55c135fd2560dc02fac68a906b1e76369be7ecd894067ebb4", - "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/flat-rate-option.json": "2c100f26341acc170df6dd705754c45619be538cfdec790cf08dd8e8e6098d00", - "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/vcpm-auction-option.json": "6fe3ad592309cf85138b09c86703c212fe4d165fd60d0b6e52356eb17783d304", - "https://adcontextprotocol.org/schemas/2.6.0/pricing-options/vcpm-fixed-option.json": "7b16a9382043bc7968d0c86db3ef513027bcc931f42550ca218b62e6e5c2e41a", - "https://adcontextprotocol.org/schemas/2.6.0/property/base-property-source.json": "8fc741ef7dc8c91edfc3d78802a7bdd2066a46a49b8ad68a8a7a8380085d0bee", - "https://adcontextprotocol.org/schemas/2.6.0/property/create-property-list-request.json": "5526ea26f57c711588e68751dd07775e1d96d4eea16e42ba600520b171cf07e8", - "https://adcontextprotocol.org/schemas/2.6.0/property/create-property-list-response.json": "0699046c948ce95337af76e2f152ec088ae125b829fc06c1d47e829c621ab528", - "https://adcontextprotocol.org/schemas/2.6.0/property/delete-property-list-request.json": "05b691930949c8a037795b3cfb5866c017669c205ad5fa22d8eefab40c824067", - "https://adcontextprotocol.org/schemas/2.6.0/property/delete-property-list-response.json": "d60093f095905dceaff553eab0dd3356202bfb1d6b96fa7c20195996ba66db82", - "https://adcontextprotocol.org/schemas/2.6.0/property/feature-requirement.json": "d46f3d3c74be646f52102524f5b3c162069af20c42eb025885ee6e965f3b9acc", - "https://adcontextprotocol.org/schemas/2.6.0/property/get-property-list-request.json": "604073eaf53a68d8a16204a28a2468592c19b267950d5fce4e1e3671b3e3246f", - "https://adcontextprotocol.org/schemas/2.6.0/property/get-property-list-response.json": "3410564dc6a05475dd46ba9ad4ddb2c78c40ebfddf1e6f139e4e30fe43932897", - "https://adcontextprotocol.org/schemas/2.6.0/property/list-property-features-request.json": "e53044fb80952bc2de02fc71bc3143563c6b50183e6a18b060b7b493ca2ca8b0", - "https://adcontextprotocol.org/schemas/2.6.0/property/list-property-features-response.json": "1a9b61a83176e8cfe1cffc13cd06b0ac4d6a383ca08d5c0ea601f421cf327707", - "https://adcontextprotocol.org/schemas/2.6.0/property/list-property-lists-request.json": "216874121f7efb29daaea1aae44bb21c25cc4819a3ab6c7e4fa97b8868c0b31c", - "https://adcontextprotocol.org/schemas/2.6.0/property/list-property-lists-response.json": "93e16d4819fcd299ac2ced111455afe2509dfabc0edce0127bf236fa1d917e6c", - "https://adcontextprotocol.org/schemas/2.6.0/property/property-error.json": "fb15030e22d36039fb579d16ce911076d678fdd92e6e234a5f55e4b02872d267", - "https://adcontextprotocol.org/schemas/2.6.0/property/property-feature-definition.json": "512640079410580aabb43f2526e7e0741511f0297730088bddfc5ffaf53f9d4b", - "https://adcontextprotocol.org/schemas/2.6.0/property/property-feature.json": "b1d8d1c033292e265b3314b1a3cc826bb3cbf4ff63921b3c8597bcd6521bb3c1", - "https://adcontextprotocol.org/schemas/2.6.0/property/property-list-changed-webhook.json": "af5f96b649c98a879d3d12f6068c060fb2e31a82a39fcd4e86fdd60ba79793ea", - "https://adcontextprotocol.org/schemas/2.6.0/property/property-list-filters.json": "0a122f5ece612f15e1fd3f37d70b916c3dffb89a697a83f94e011464a7649598", - "https://adcontextprotocol.org/schemas/2.6.0/property/property-list.json": "a79fbddeca1b5b3ff2dfe7eb02a6db4e4125da356fe6a9b68489a344f7404efa", - "https://adcontextprotocol.org/schemas/2.6.0/property/update-property-list-request.json": "b3831277ca98805fbb3ba9ea6aceeb54d6b1694ff470a770feaae6897aeb4054", - "https://adcontextprotocol.org/schemas/2.6.0/property/update-property-list-response.json": "08983661fd168907f4899d1f972c064fd192684d3cf93bfae57289b28d19c084", - "https://adcontextprotocol.org/schemas/2.6.0/protocols/adcp-extension.json": "72f179773a44305914c7439f7a47a209c2294b08087b157210a42da0a8eacb23", - "https://adcontextprotocol.org/schemas/2.6.0/signals/activate-signal-request.json": "afa9b3023801fe0589e6bf54c26f9df0dda30362dcf5d59c90693db4f2b7c55a", - "https://adcontextprotocol.org/schemas/2.6.0/signals/activate-signal-response.json": "6710d1ee820f9f887ceaf34cbafffc5cc93441caeaaf9a3cc91742ad60c00d52", - "https://adcontextprotocol.org/schemas/2.6.0/signals/get-signals-request.json": "2df5b4b6e1eed5a5df373a255cda5549bd84eb1dca9a1bb4a5449656be2992ea", - "https://adcontextprotocol.org/schemas/2.6.0/signals/get-signals-response.json": "d6037997c5beae4a7043769f8b8c56530f27357d6fc3bd349a6377e6d886be43" + "https://adcontextprotocol.org/schemas/latest/index.json": "d8dd5cc61b2e7b7b351fbccf20288214b0f6eaa7e53d9708cdb8955a3f125db7", + "https://adcontextprotocol.org/schemas/latest/adagents.json": "585f06ed0f898c207531b208706d66fb2fe8c184355e8e332aa6dd14697cb537", + "https://adcontextprotocol.org/schemas/latest/content-standards/artifact-webhook-payload.json": "a5ddff12ff1d6316636919bc87359980512e63ff688d4b742628ab06b91b537b", + "https://adcontextprotocol.org/schemas/latest/content-standards/artifact.json": "b499571575b8e0f11b5c21dd32189fd19191d32a795cff225165fdfd0092917b", + "https://adcontextprotocol.org/schemas/latest/content-standards/calibrate-content-request.json": "fee8b02f136fdbcbe9ca35879d71f19cf37349de9b047e1c6e7e65b91b23bc3c", + "https://adcontextprotocol.org/schemas/latest/content-standards/calibrate-content-response.json": "55b76ae2eb728abc8b5dd9d5d2f3af25a4dc6c31c06d8a76db5d4544e6001ecd", + "https://adcontextprotocol.org/schemas/latest/content-standards/content-standards.json": "f6cc2b2cdb83494c7f11a15bc1e4118eecca4f6a9efa11abcd03660eba4bbd0e", + "https://adcontextprotocol.org/schemas/latest/content-standards/create-content-standards-request.json": "025c2495689f85d209fba6191b74d070e0db58e913d355dc1e9cbf80dcc8ec72", + "https://adcontextprotocol.org/schemas/latest/content-standards/create-content-standards-response.json": "9c5cf7b12680c14ce13542d0c032f7b5135a0546a917147aac8633bd43618ec5", + "https://adcontextprotocol.org/schemas/latest/content-standards/get-content-standards-request.json": "abe28cf4158bfa4f4333734639e62fd4d3057ab9fbc8eed0e121e51ac6962004", + "https://adcontextprotocol.org/schemas/latest/content-standards/get-content-standards-response.json": "2b857288ce95461fd5e278fe27d6a21dbb06c442ee2a8f41db2530e547280991", + "https://adcontextprotocol.org/schemas/latest/content-standards/get-media-buy-artifacts-request.json": "62866c85ca88dd674c89b9be02e875b599265875368802b6a8c7c8564bd4c607", + "https://adcontextprotocol.org/schemas/latest/content-standards/get-media-buy-artifacts-response.json": "bdac754a8fafed7152bbafc42bfa4abf2ed85b6e8feb5ac952be731748ecd751", + "https://adcontextprotocol.org/schemas/latest/content-standards/list-content-standards-request.json": "0a877b8ecdc7b95fff4943a51f79b0f73a145dbe29914b3b94a85ac7490ea051", + "https://adcontextprotocol.org/schemas/latest/content-standards/list-content-standards-response.json": "9a1add4101da91e188e95a893ae50ec6c7eae6b3dc9cecb14c9edddf0a9a4c2b", + "https://adcontextprotocol.org/schemas/latest/content-standards/update-content-standards-request.json": "b0b5ad96853c0f90870716ae855b2d683d168859cab32d1f67afed7e734c014a", + "https://adcontextprotocol.org/schemas/latest/content-standards/update-content-standards-response.json": "b309ab5a2e0b666e4ecb1d5d4c29bd8992f469bbcff39368dfd8bce1386a2fe6", + "https://adcontextprotocol.org/schemas/latest/content-standards/validate-content-delivery-request.json": "5744995b40f3ca06a6ba7e33471bfa2ad4358ddf12788b4f53faaf79b27b47e7", + "https://adcontextprotocol.org/schemas/latest/content-standards/validate-content-delivery-response.json": "a3223d796114054b90a67ebff460286a5231f956cfbbfae2398fef518dfe3b55", + "https://adcontextprotocol.org/schemas/latest/core/activation-key.json": "a31fb82057c50037575304641bcb32999239a762d93c1b3f1c5f535678c898a6", + "https://adcontextprotocol.org/schemas/latest/core/assets/audio-asset.json": "d67d87e0154701f10a765cd28039347ce7971245553bfb5937e4eee30ad93a73", + "https://adcontextprotocol.org/schemas/latest/core/assets/css-asset.json": "b37b137ff038e3b147d52fdcc221e6961fe3f3caeb62b4e3f2356cb448ed7500", + "https://adcontextprotocol.org/schemas/latest/core/assets/daast-asset.json": "54639aaa0060dbbd829b2c249a8c5c63e5eeb999e8194dd76f8024f0150d4a1a", + "https://adcontextprotocol.org/schemas/latest/core/assets/html-asset.json": "aef879b07dfabcfd7f77e07407f7d9236720ec72d4115ca580598a545e7bcc97", + "https://adcontextprotocol.org/schemas/latest/core/assets/image-asset.json": "747825615f570c814335eb15fbd6f59d205bbb063b28e1a0cecd22c4403bbfbc", + "https://adcontextprotocol.org/schemas/latest/core/assets/javascript-asset.json": "f5a767629f465947117b4ce676a84981cd072d8e155c4a069a8688c2308aec8f", + "https://adcontextprotocol.org/schemas/latest/core/assets/text-asset.json": "b6a9bf1dd18971ff368d4d2d9c3796705e83c82898bb8672eda6a684149f42d4", + "https://adcontextprotocol.org/schemas/latest/core/assets/url-asset.json": "96ce5efde3ef98bba10d8ea9a43d8e778229b6bc1b44e5348e8380499e192fdc", + "https://adcontextprotocol.org/schemas/latest/core/assets/vast-asset.json": "70ed74213638492b380ffc4e596e630b47c838875f658b347819ba6236ba4d82", + "https://adcontextprotocol.org/schemas/latest/core/assets/video-asset.json": "521636afb19b566daa6a849e3da86a00da76a5766829aa58439e7c373bf59f1c", + "https://adcontextprotocol.org/schemas/latest/core/assets/webhook-asset.json": "2ccd0831bc7a91a6b41a071fd994fe55a6e6302b85059ad440c5229793ff6d41", + "https://adcontextprotocol.org/schemas/latest/core/async-response-data.json": "b3e3e57e1a121067cdd6392265223a14b89ebb27220a18d822ffdeb09e7b7523", + "https://adcontextprotocol.org/schemas/latest/core/brand-manifest-ref.json": "10bd77dc7e07fb8e8a0665272c18cdcb7f05afc72856ffd66e6f2505431d7612", + "https://adcontextprotocol.org/schemas/latest/core/brand-manifest.json": "c8dcca23ee3b527a44ee60fa66406a9ab441433832812671269dc1a92ce45230", + "https://adcontextprotocol.org/schemas/latest/core/context.json": "b5b5de9482d662c1eacfcfdfa53de672a047664e295940cb204f2d822d5eeb31", + "https://adcontextprotocol.org/schemas/latest/core/creative-asset.json": "690aad4582c719aa7b106c6af0a8b7a2b021575d1f0945c666c07cdaacd70a35", + "https://adcontextprotocol.org/schemas/latest/core/creative-assignment.json": "b62b9db75d306abe2e5f097aac1caaaeb214c0b22d37f58d63ba3f5c428f4f10", + "https://adcontextprotocol.org/schemas/latest/core/creative-filters.json": "0095157d0cfe6fcff2299f438a9f27e6d9c9cde23174034526a9974e228ad05b", + "https://adcontextprotocol.org/schemas/latest/core/creative-manifest.json": "e340b49ab2ab88ead4698a5fccde77cd0bbb288e5594b1f97647e66a7593ba96", + "https://adcontextprotocol.org/schemas/latest/core/creative-policy.json": "c63d0489e8d7423b49471b3ceeae3df6716e5313a842bdf881dfa4e1f3516e6c", + "https://adcontextprotocol.org/schemas/latest/core/deployment.json": "5769c02297e584f761a55301732621e22f8166e9806a1933cb842c1be9902914", + "https://adcontextprotocol.org/schemas/latest/core/destination.json": "007880839e1d556972365ba1cd7076d081bbd6e6b9b0ba47147fc2748ce60d35", + "https://adcontextprotocol.org/schemas/latest/core/error.json": "97dadd80893ba1c3d371e7b3fefe33941e3b8e660e91d0e8e1517c5144851b1d", + "https://adcontextprotocol.org/schemas/latest/core/ext.json": "0dc59d0cf5bcf97f9ce9ba635f977ec65b982e853cc0b05decb034cfb642f4b5", + "https://adcontextprotocol.org/schemas/latest/core/format-id.json": "529433d6d5ecac7514d85a0bdf80caf0a69a3c5c0f77a14932441a954a8ada15", + "https://adcontextprotocol.org/schemas/latest/core/format.json": "968a8b47a576e9f352fa60a4350078cf8badc9de58926a881eefde896c7aa3d2", + "https://adcontextprotocol.org/schemas/latest/core/frequency-cap.json": "78e7d100a8f99c59d8190f487a868bac804a25a3797c06b8e668e782c0fe0dfb", + "https://adcontextprotocol.org/schemas/latest/core/identifier.json": "da78a993f66120ab06fbb6e4801a3806db72c6e5ad990c9565965b8c8b625fca", + "https://adcontextprotocol.org/schemas/latest/core/mcp-webhook-payload.json": "1dae520cb0c0564f4c647a5fba4cb8383897f28dcf72a2d046986684255f099e", + "https://adcontextprotocol.org/schemas/latest/core/measurement.json": "069685e5f69b28598a35e6887a289f82ea830c1d9c0a8c99e621d3c1a96c72fd", + "https://adcontextprotocol.org/schemas/latest/core/media-buy-features.json": "6d0eff2e73aceaa9ff53efa06b21b017b51ffb9f41f365c2b6560bff6583be07", + "https://adcontextprotocol.org/schemas/latest/core/media-buy.json": "85070c512df5bd86f7aeabc2bb03a902c0895d89d165f477576c410995b89018", + "https://adcontextprotocol.org/schemas/latest/core/offering.json": "4a4e959938a191e74918ca48a506a90a0074584a7d1e6091b70ca35cd71e7657", + "https://adcontextprotocol.org/schemas/latest/core/package.json": "ed37f06989f3936fda9caf03201ffe30b120a4bb47251c3fd85e5cad341737fc", + "https://adcontextprotocol.org/schemas/latest/core/performance-feedback.json": "63dec657c26dd2702d9051d151d428b97ce8ad427fea8571c571a8eb8f53d99c", + "https://adcontextprotocol.org/schemas/latest/core/placement.json": "2b5a7cd544e2ef14d03149b3fc47700ca4559604c5bc0c233bf44e2b2e8b50ca", + "https://adcontextprotocol.org/schemas/latest/core/pricing-option.json": "f4f99dac2a28722dd3ce0ded62e8b93a295ba5fff43de6c3d1419e0cfccf4e12", + "https://adcontextprotocol.org/schemas/latest/core/product-allocation.json": "736a415a81e9e28337975eb5c7d948e4edc3512b2bcca9331656993e86418d30", + "https://adcontextprotocol.org/schemas/latest/core/product-filters.json": "d067711fb1cca672d70a1340ebd4d9a59cdcba591c521e229f27770764668af3", + "https://adcontextprotocol.org/schemas/latest/core/product.json": "3c7cedff87c61f2761e61a381063e9bb4ed90a8578f6a415566aadf57d0afff4", + "https://adcontextprotocol.org/schemas/latest/core/promoted-offerings.json": "cb9976da4643b54ca64284a25b7a8478935d196f0eaf1453cd9b369678b1065e", + "https://adcontextprotocol.org/schemas/latest/core/promoted-products.json": "8046efb31fb8e0c8c009123591a5446ee9db684f20f9d46c5f3f7e78492231b9", + "https://adcontextprotocol.org/schemas/latest/core/property-id.json": "16ff353402c03691a7290a0f7578a901b63a0f7e83567b8903c5c6f89e1fb6f0", + "https://adcontextprotocol.org/schemas/latest/core/property-list-ref.json": "50c908159f9d02bff2a3330ac1bdbe2a46c47649a3efbc0a8eb9f8118b3b70bc", + "https://adcontextprotocol.org/schemas/latest/core/property-tag.json": "6f2c35324ca6c5533a2c3d1a5837360c813a0905be68b11da7a46965ec37d59c", + "https://adcontextprotocol.org/schemas/latest/core/property.json": "f81a2eefccc2ebf38db5c08a6aa99935fb03736a5abc946a4a4aa72a47015349", + "https://adcontextprotocol.org/schemas/latest/core/proposal.json": "440619ed4ef8dfb877509ea2e383b130d22a0f3e5422916ddf8f51212fba7754", + "https://adcontextprotocol.org/schemas/latest/core/protocol-envelope.json": "38fca1729f9a8cd242b5f081559f195b097bb3e0f36456a53af30d0c8212015c", + "https://adcontextprotocol.org/schemas/latest/core/publisher-property-selector.json": "2763ecac8effc1e27bf69d231968f25bad5ee2bb723ad1bf9c3da125d6b64099", + "https://adcontextprotocol.org/schemas/latest/core/push-notification-config.json": "64ed4db710d5a5346d6935e238d28ffaa4374dcff9d08e5d4283d4786dfe6de5", + "https://adcontextprotocol.org/schemas/latest/core/reporting-capabilities.json": "6aad28b1d8a7793035cb97c0b92e569ca6caae7def439a679169519764fbe2b2", + "https://adcontextprotocol.org/schemas/latest/core/reporting-webhook.json": "90e90d454334590670cfb881b14be00dd2a7fc134b0cc4494c79c6848fc2db1d", + "https://adcontextprotocol.org/schemas/latest/core/signal-filters.json": "e2558d771937cdaef2fb278db6bc56e57078aeafacc1c0d83cfd378b17812117", + "https://adcontextprotocol.org/schemas/latest/core/start-timing.json": "8e07e0469f434f3d3ba998e2b1fe58fc3dd097915e2d5e0c547cadfd5a469158", + "https://adcontextprotocol.org/schemas/latest/core/sub-asset.json": "c0293416fd0275afd5ef59bd68675ff8ea37e4d4ba8f3a13e375711529a6399a", + "https://adcontextprotocol.org/schemas/latest/core/targeting.json": "59224c362353602192d617a61bb66326c834e2cec09a138d90906d7f2241cd22", + "https://adcontextprotocol.org/schemas/latest/creative/asset-types/index.json": "9dc55de12aede8e02b24acc2e8f9e61a94365b897ab065f87896ed0ae5e6eb56", + "https://adcontextprotocol.org/schemas/latest/creative/list-creative-formats-request.json": "3997894b7d40e2ae95107e872dec2549f1b445cae0c606f77a4949825e1741d0", + "https://adcontextprotocol.org/schemas/latest/creative/list-creative-formats-response.json": "160adbe2020191bd6ded0b094ea6a2e5ca9cb814f468e1bb70326ee59b7df1a3", + "https://adcontextprotocol.org/schemas/latest/creative/preview-creative-request.json": "5f4f3095501e3fb1fd8f46815d963326a57b452c85b6c42ed4dc64cf8b928029", + "https://adcontextprotocol.org/schemas/latest/creative/preview-creative-response.json": "caf1adb408cb6f9e07ab8eb33f683af118294f632cb39e1deaa8d92beb846056", + "https://adcontextprotocol.org/schemas/latest/creative/preview-render.json": "b4837c5a4027d7034f90ddf914c2e5e1a90e4ba6ee76f68a1b622e8a6cf64fc3", + "https://adcontextprotocol.org/schemas/latest/enums/adcp-domain.json": "5f13f5da2b16c09e2b99ba8960356a03c92f6fb7758abe3ec33ff46050e78eba", + "https://adcontextprotocol.org/schemas/latest/enums/asset-content-type.json": "74414bc886efb8a52794da63cfbb873befd9d24c87d9293ac88008bd496dfafc", + "https://adcontextprotocol.org/schemas/latest/enums/auth-scheme.json": "492732201479760e022e7e20461874312403dab836af0f45c1382fd7b59c8b17", + "https://adcontextprotocol.org/schemas/latest/enums/available-metric.json": "30577d384f8ffa1f6b9285c59878dbe0d55b090ea9e9ae765efa9fe4aabd3825", + "https://adcontextprotocol.org/schemas/latest/enums/channels.json": "90cb43e6cca0dfb9f6424768a3a21d5200182eab0e998f50d2f3c91901fa3d22", + "https://adcontextprotocol.org/schemas/latest/enums/co-branding-requirement.json": "7d533d01abfc5b134985e4a4611547a8d88601f2ad3dae166d30483433a5af8e", + "https://adcontextprotocol.org/schemas/latest/enums/creative-action.json": "c8f56831b63d868ecdadb81787fbd9bda85f791387cc04d10a4f3f4774edf591", + "https://adcontextprotocol.org/schemas/latest/enums/creative-agent-capability.json": "1393bde9696600816f802091fe73cd8553c305e039b8f0e39493b5112e4f9d27", + "https://adcontextprotocol.org/schemas/latest/enums/creative-sort-field.json": "adc83644f01b9948aa436c79dc0701d878a876e185adf7808485772fbad5eb28", + "https://adcontextprotocol.org/schemas/latest/enums/creative-status.json": "d8c83590a233ec9e605c63ee8fa009bb7fb5b5336092e8bef0386f226cc0a5e3", + "https://adcontextprotocol.org/schemas/latest/enums/daast-tracking-event.json": "caec0a9b0852c26a43a41c52312a36007656f7104c5af276d1111dddca9e2041", + "https://adcontextprotocol.org/schemas/latest/enums/daast-version.json": "95b06e213a2279ad3db0cca8912324a7773bc90a28bd0a39c676f73dcc4c70e2", + "https://adcontextprotocol.org/schemas/latest/enums/delivery-type.json": "3934bfba9af3ef9469f73b85b15c61c058b79771e74ae7bc387afc95905feacc", + "https://adcontextprotocol.org/schemas/latest/enums/dimension-unit.json": "405de49a9144c527466677ef3d3e5010b3cecea289f74b837958496da78045fb", + "https://adcontextprotocol.org/schemas/latest/enums/feed-format.json": "2147a55d3ab95d8108f6258d31c2ea3e37f32eef065af05236135600f4eb9c99", + "https://adcontextprotocol.org/schemas/latest/enums/feedback-source.json": "56283eec28ab10c8a11f09959c0f3dbef2b5bf02b7df84599343cb9fb0e69f78", + "https://adcontextprotocol.org/schemas/latest/enums/format-category.json": "12e5642d281d4657de9039e7a41af4ba72cc8cd3b0b72fc395f42d760a62789d", + "https://adcontextprotocol.org/schemas/latest/enums/format-id-parameter.json": "0783749a5ac1e2eff4cc523eec16e3a723e107b3718bd55e1bc671cf230b0a1f", + "https://adcontextprotocol.org/schemas/latest/enums/frequency-cap-scope.json": "3275a767cbde71235e7a23d0d775b5d58afb1859936393b04eb2c7c976ef2493", + "https://adcontextprotocol.org/schemas/latest/enums/geo-level.json": "e6b65de7e6699c4171eba799553a39f8d3bdc787242ef7bfa269b6f6d77a1bfa", + "https://adcontextprotocol.org/schemas/latest/enums/history-entry-type.json": "e77c87be1493e84d83ffb567113303e2b50baa1dbd8c1ea791e2e8822f2bbf64", + "https://adcontextprotocol.org/schemas/latest/enums/http-method.json": "75c12b6e8868b0248841bbf8e666fd097308276f59a2c8f809fa279a88c06188", + "https://adcontextprotocol.org/schemas/latest/enums/identifier-types.json": "73190ea41c388af5b6b9c56358c4bce893b0f7cf61bc5062647f9987755451ed", + "https://adcontextprotocol.org/schemas/latest/enums/javascript-module-type.json": "da4746acdce608ce9497f59e7fdbc97a649367e55aebe4b9675feb3176e8525e", + "https://adcontextprotocol.org/schemas/latest/enums/landing-page-requirement.json": "5a09b76855c541b23ccf1aaa8ea87e77203d358b5c01c1b255722f21ac6327a4", + "https://adcontextprotocol.org/schemas/latest/enums/markdown-flavor.json": "df8836754968fb1c02fc7725aa1bce56e315c4cec11515a19058b5d6a0cf782b", + "https://adcontextprotocol.org/schemas/latest/enums/media-buy-status.json": "70bd2fca8832137c3b504c4b80934fdf8a57bcb45c4e1bf821fc49096aae53f9", + "https://adcontextprotocol.org/schemas/latest/enums/metric-type.json": "41eafcfaf6206670aabecd65abd5c1f2d0c4af019a3e4055d26aecfdccfd0a75", + "https://adcontextprotocol.org/schemas/latest/enums/metro-system.json": "f8cde6b0bd45c4fbabef8ff90e01c57ffc8d5a821d7f50b94de48a6ed7cf1641", + "https://adcontextprotocol.org/schemas/latest/enums/pacing.json": "6fb8e62bfdc40bb48e0620ed71310f21a821fdfbe644c625d01b6a68ba4e40bb", + "https://adcontextprotocol.org/schemas/latest/enums/postal-system.json": "20651c3197e7554ced864c3addb71a27ac257952988e5248db8f6f882fad12d6", + "https://adcontextprotocol.org/schemas/latest/enums/preview-output-format.json": "b14841f4e6689b3a3d2afa5740b4787ba49961d39ede2f9b92b709ad7970b32e", + "https://adcontextprotocol.org/schemas/latest/enums/pricing-model.json": "eb2aee267593d91e7f02ee0143fd8c2226021560fbee6b7ad983188f216f5f5a", + "https://adcontextprotocol.org/schemas/latest/enums/property-type.json": "7e047eb116c41b4682818f89c8b19573636a546500289d48be189945318ded83", + "https://adcontextprotocol.org/schemas/latest/enums/reporting-frequency.json": "b480016e39a0b8a4493e55f5bda13b153e8df7c4c07ee49586cd77bdfdab0af5", + "https://adcontextprotocol.org/schemas/latest/enums/signal-catalog-type.json": "f899ae2550950b3e2269f42c20c50bfd09c1f2870fc656e334b73758bfbf2245", + "https://adcontextprotocol.org/schemas/latest/enums/sort-direction.json": "85a2cf23403297069995f14498a495c566a5a8bce4409d468d9071e18338ce6e", + "https://adcontextprotocol.org/schemas/latest/enums/task-status.json": "b45adb6b28b0b35ea5cf5564ec22d7b692e66c40d10d891d6dfe6661035c82b0", + "https://adcontextprotocol.org/schemas/latest/enums/task-type.json": "f15bcd10ce1870246f88c8db5878fbb9b3993806fe18072226271fd9a095774c", + "https://adcontextprotocol.org/schemas/latest/enums/update-frequency.json": "657d0460d5675ddcd7edb4cf92655b56a93cd724ab3c0b4094241ef91ca644c8", + "https://adcontextprotocol.org/schemas/latest/enums/url-asset-type.json": "8cb3c557a43a0d5f85cd9c7b83366910c570349c6ab8625583ca66454fc88c03", + "https://adcontextprotocol.org/schemas/latest/enums/validation-mode.json": "0df6bb0c18921714d48d26c2813d6fa312c5a671e1a421f9c9f9ca0c0cfa6811", + "https://adcontextprotocol.org/schemas/latest/enums/vast-tracking-event.json": "c13b3a90cfa3f13f9446185a366095576b1b92574fc468c7de432c8c141167a8", + "https://adcontextprotocol.org/schemas/latest/enums/vast-version.json": "cf0f0e11eba22c9679b96f13608540016dfa3423101b8e22238ebb56abd224dd", + "https://adcontextprotocol.org/schemas/latest/enums/webhook-response-type.json": "72ba18db0a6fabd814195e895841e4cd6af5b54c4d6a954552c36284da5c4075", + "https://adcontextprotocol.org/schemas/latest/enums/webhook-security-method.json": "80c1a7622b750af3bcfd2695569a3b348e42d5c8614378c27a65f8c7374e9165", + "https://adcontextprotocol.org/schemas/latest/extensions/extension-meta.json": "639103027d657206b40a9bdfff0baded2588835e6f15e5b0f7acfec748e94423", + "https://adcontextprotocol.org/schemas/latest/extensions/index.json": "7dd5e1b375a9f55d0f87313858fadf169e869d1802f16aed296d70247184007a", + "https://adcontextprotocol.org/schemas/latest/media-buy/build-creative-request.json": "0eadf98c199f8b29475a600cd9bf6d71cd6adb135c4e2d65cf7a0ec8efb5f566", + "https://adcontextprotocol.org/schemas/latest/media-buy/build-creative-response.json": "67c3e0d4b3f0c641e7e86833ab5e54c872d9cc79e673bf414abb412c81853973", + "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-async-response-input-required.json": "397bb7a973f943bdb2c53b36822c93ecdc815d3e5184a1129cad8648d88f378a", + "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-async-response-submitted.json": "7c9502344a561c3aca8752e6d95918444eb905b82413af0c6a8e4782963ce4f2", + "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-async-response-working.json": "f8023b1dd59955843ecf2ee3c79a81ca83411ced35daa58a6e7210ad88678e00", + "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-request.json": "b0fe4b12e80e79dc7269281e627ae0882ccd5d5b48520563209be24f359eac0d", + "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-response.json": "02e3fb22715890ede07cf7fa976b2d2025754b3cb88aa68be3c3479fdb7bbea5", + "https://adcontextprotocol.org/schemas/latest/media-buy/get-media-buy-delivery-request.json": "4c2c5c3daeadec0dd8c5f3284cbd552905cf3987b10135ffb3bb87f05584c229", + "https://adcontextprotocol.org/schemas/latest/media-buy/get-media-buy-delivery-response.json": "6abd494e57bd0f43ad5089bc438d116e9c74892791c3fbb9db669e859627457c", + "https://adcontextprotocol.org/schemas/latest/media-buy/get-products-async-response-input-required.json": "107e27baf08f80a97a0de83a24faaf37cae5c0c3112ba707ff191af1c2ad4ea6", + "https://adcontextprotocol.org/schemas/latest/media-buy/get-products-async-response-submitted.json": "f0cbf91c1e1ccc5e2c84739b8ebfbbf73cb4f64d0067847bc3eb19ec1992aa72", + "https://adcontextprotocol.org/schemas/latest/media-buy/get-products-async-response-working.json": "62be745552eeaa0aa72fc8a06b0dc89d138264ed5150158f1061cd5043c99dfa", + "https://adcontextprotocol.org/schemas/latest/media-buy/get-products-request.json": "8a6f9f070496672bc4fde308365151f2728e79bd37f5aa5be88f02c24213563e", + "https://adcontextprotocol.org/schemas/latest/media-buy/get-products-response.json": "ae8b93b0a835a31ef4d10fdcf2e0b84973787c493d5b0b854704e710987d9d40", + "https://adcontextprotocol.org/schemas/latest/media-buy/list-authorized-properties-request.json": "d37a2afc3ab7e41ae710b5d6c5b453a1761d5abf847390bf8264ef1343718ccc", + "https://adcontextprotocol.org/schemas/latest/media-buy/list-authorized-properties-response.json": "ab37432a1f5f636f3fc61301ab8a09ef08cb2f386de1214398050a254a00a095", + "https://adcontextprotocol.org/schemas/latest/media-buy/list-creative-formats-request.json": "3a461cc008ad80d2e62638d221fb76e32262579f06777a7662e3d88073b23c53", + "https://adcontextprotocol.org/schemas/latest/media-buy/list-creative-formats-response.json": "99fb49bcc8163473bed55d9c9daa242d561f09f55acd94851a9c0bac2c907397", + "https://adcontextprotocol.org/schemas/latest/media-buy/list-creatives-request.json": "d45bc1bdcc9dca066c2430992b30dd6c9b37ce667957bdc2d1048cbe250b7a4c", + "https://adcontextprotocol.org/schemas/latest/media-buy/list-creatives-response.json": "9fe8f7628332bb3a4c6f146529b34a609cb210918bac7e058dd39835a007384f", + "https://adcontextprotocol.org/schemas/latest/media-buy/package-request.json": "11d3ac74b3d07a2b16165f34cbebed8e688565115e45c722dedf1d0663f8d819", + "https://adcontextprotocol.org/schemas/latest/media-buy/package-update.json": "6cd7b8089cd0b3179ef66b161f9bdd6a42dd6007be7401bbc0a96bbd48337bee", + "https://adcontextprotocol.org/schemas/latest/media-buy/provide-performance-feedback-request.json": "8fff8a6e58cf2f8dd95e2e1cb53ef1b3c2154991a577547a2f8c75028867a81b", + "https://adcontextprotocol.org/schemas/latest/media-buy/provide-performance-feedback-response.json": "bebd13943d48ad8e8b419bd69f9fa2a9b4df30c379ae74219904e698231e7371", + "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-async-response-input-required.json": "62b4e86135542f4076b7bcf6edf157a7bb919e168ea97d0afb1ef1fe4ff2b8dd", + "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-async-response-submitted.json": "0a6df44b4224a4b38d25673d0f813022e124c7ac0bcc7eccb95e673849af7368", + "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-async-response-working.json": "5a336a8217d13fa112ac3dd1ed2d2c707f8abd9bb9ff05af674c22138dc24c90", + "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-request.json": "01cfece0e07ba8825656aec890bd2e9293918d41695d777ca70d684f626d19d6", + "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-response.json": "1fc6bf8348c520aaf2ec2041b64f50307de7edc30e54dc0de81e36af88e2833f", + "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-async-response-input-required.json": "73ecee00cf0babc200778621b78148a54327df3436dedf349d83c734a99fc4e4", + "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-async-response-submitted.json": "d4736323140cf6db5522e1de5aeb1023f8a7b608d319ede26b86d28c57bea0ef", + "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-async-response-working.json": "ccca3256ac3179a2125922718efde61367b9046bdfdee156bdaa72c1398f2ed3", + "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-request.json": "11ab339a8e3dae8a5f0d9df0b680eb7acfe96c294922b5b1678e6e302c1f6b76", + "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-response.json": "aca3e048a43704e0f7dee2370c4ad4c4b662805e4fe39b3dde7cfea3bba1101c", + "https://adcontextprotocol.org/schemas/latest/pricing-options/cpc-option.json": "dcd9048d2eb46871c101f9167af24c0a3d28f291d3e5fd9f77281c0460921f5f", + "https://adcontextprotocol.org/schemas/latest/pricing-options/cpcv-option.json": "7de0c760be37a96ae526de23c9312506bd15a924d42cb4621d48b4ee156dbb83", + "https://adcontextprotocol.org/schemas/latest/pricing-options/cpm-auction-option.json": "1a45dbe8390ce10e58b7485bd1feb2d9b399fd2fdf25363c783b38b56959750c", + "https://adcontextprotocol.org/schemas/latest/pricing-options/cpm-fixed-option.json": "c02d668c229fc0a5f959cab122008298a3b515afcc4ba0d6bc90a5a838667e39", + "https://adcontextprotocol.org/schemas/latest/pricing-options/cpp-option.json": "fd571e844444d2e6de3ea2e1595dc66d1d06d28346cfe3e1af856f716b541215", + "https://adcontextprotocol.org/schemas/latest/pricing-options/cpv-option.json": "75e6545731c747c4e0ab5522239700991de91fc91739b988855cc6e89c36f38f", + "https://adcontextprotocol.org/schemas/latest/pricing-options/flat-rate-option.json": "515ec3319bb25437f8302c6ee89e51d1164e14d6a88d0a60391ad2184f8e0430", + "https://adcontextprotocol.org/schemas/latest/pricing-options/vcpm-auction-option.json": "ae7f4d71b43e51a8eb7411bd0509a6b1618834ac28b6c74af31ffd3cf47f2f55", + "https://adcontextprotocol.org/schemas/latest/pricing-options/vcpm-fixed-option.json": "0ae515fd9be111cd8bbd6029f2ffcb0afaaf565c1fcf96a483f5fa98cb993cee", + "https://adcontextprotocol.org/schemas/latest/property/create-property-list-request.json": "9b96c2cbe21edce3c6645c7bf7947399cc86cb8cc72b236a862150d6d79e5482", + "https://adcontextprotocol.org/schemas/latest/property/create-property-list-response.json": "b7ceada500f573191cd0ef9e07817cb35f5e1b2dc1180cb15a231db460ee1655", + "https://adcontextprotocol.org/schemas/latest/property/delete-property-list-response.json": "222fff1b07bd9d20ce0a4db6a723ed7d86b9b34ea9e5139394c444275586c4e5", + "https://adcontextprotocol.org/schemas/latest/property/feature-requirement.json": "16e9f8f0f8a3e5150f264698be1ec1a68aba0999cf5d6c11ce26b2d0bc72bedb", + "https://adcontextprotocol.org/schemas/latest/property/get-property-list-request.json": "99edd1056bd089fc32967b42f8e33dbb90b68e46ff8a2d9a627e5ec79aeb47ed", + "https://adcontextprotocol.org/schemas/latest/property/get-property-list-response.json": "436570d44119ee309d53855e7ac82ee6ce002282502154c3f5187710848c9372", + "https://adcontextprotocol.org/schemas/latest/property/list-property-lists-request.json": "cd3f516ea9ae6125e2aefbe3c4e99e8ba34c6fb904fb84e5d957ac00424f708d", + "https://adcontextprotocol.org/schemas/latest/property/list-property-lists-response.json": "6fc916fa5e652d48f24198a6c39bcfa88efebf8d774d211aae08a90cb09839e6", + "https://adcontextprotocol.org/schemas/latest/property/property-error.json": "7077c4776c1e46d6b1284750843c502193009fb7cc912a967710419fc30fa200", + "https://adcontextprotocol.org/schemas/latest/property/property-feature-definition.json": "ebc923cc3a122970f62bc0494ccfa222ea5083673babb7c0dfdf4b90eb6d13b6", + "https://adcontextprotocol.org/schemas/latest/property/property-feature.json": "f6bb5d571b0c9cca78f4f97e867651a8798103ba3eb460cc87c7f9144929541a", + "https://adcontextprotocol.org/schemas/latest/property/property-list-changed-webhook.json": "4bb10e21aee5c58dc64fa0bba9e79798d3aa958e1eb02a6f028ea1799f5c03bb", + "https://adcontextprotocol.org/schemas/latest/property/property-list-filters.json": "3cb8fc41a4610ea235cfb4e3be148d0849b6eefd232858fb28ea61430aaed4fc", + "https://adcontextprotocol.org/schemas/latest/property/property-list.json": "ab0c4606a853ea0a1440f0d2b1bdb5c0bb6017e5dc67e090c6b5b3ea5670bb27", + "https://adcontextprotocol.org/schemas/latest/property/update-property-list-request.json": "85e5254572caef47fd88be9ce36f983df889c089e04d07c94b05ded9a2e6b7a8", + "https://adcontextprotocol.org/schemas/latest/property/update-property-list-response.json": "3d5e6ceca2d6273c77bab370725e41b95077deb2f55f37ca62ce440c8353b1ca", + "https://adcontextprotocol.org/schemas/latest/protocol/get-adcp-capabilities-request.json": "7d6321d1997b602fcca7d2ab9a9ac6192f31d38f80b03dcf61dc86242b49f8ef", + "https://adcontextprotocol.org/schemas/latest/protocol/get-adcp-capabilities-response.json": "b5b9df6de58d771a0b8840716b068d24f526866e3594dda5dba10a90be45b287", + "https://adcontextprotocol.org/schemas/latest/protocols/adcp-extension.json": "540c825cdd7e3040e2a7500f48f58401176d0e7e5a3d350bfb74d4ca34b1e651", + "https://adcontextprotocol.org/schemas/latest/signals/activate-signal-request.json": "5791ed345768830e7e0eaf72d03027384550ccbd79b9acc5ef45c5f34bf705f2", + "https://adcontextprotocol.org/schemas/latest/signals/activate-signal-response.json": "9da0bccfb7c1534f9a279f6689b6771a38b15e2064a01ec1b310a44bb14aa733", + "https://adcontextprotocol.org/schemas/latest/signals/get-signals-request.json": "c52ee37c34bfa9fbc0ea952f28c69c33cfb4e209c5372e0e4da8697061350ba5", + "https://adcontextprotocol.org/schemas/latest/signals/get-signals-response.json": "d928cca512cd9178bf60c6b9c52ba62da8d20d90ae68cc8745739c8d82aa71a4", + "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-capabilities.json": "47e6b508f051d6ebb1551b4516ddd67e455679c8e9dfec37e5bf1019f31e2616", + "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-get-offering-request.json": "953346b451471a4c930649fb5dc470361763009b1a2efa0f4666a0b7acfb16c9", + "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-get-offering-response.json": "e0cc6da05594aa7080319bbc506cf56d3f7c541504cde86e27573917078410e8", + "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-identity.json": "6b1fad0cb8433b15055b7e2a8271d7ee1ac405db6f5e19bb9aa8eb405a747797", + "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-initiate-session-response.json": "3eb8440b2be7b8d4777003b34f3094fd6d1c6b87a3236163d584192352b0c7f7", + "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-send-message-request.json": "b8a789094d4288cf277070e762f01bb22b3248c9730797603974891741bbc3a4", + "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-send-message-response.json": "6c3e693333c009d37a45678ce73d9b3ee0bcb7ea3a4089187f0ab422dd04df97", + "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-terminate-session-request.json": "8121c3cbf497bef6e5b265a3520daa8cb1c38cd133e8d593b4558f175f7fab95", + "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-terminate-session-response.json": "446b2ff92b8522d805af1592334d56c045e891608bc87f751007c8afe552d188", + "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-ui-element.json": "e7d434246c38e1d047896cfdfec30ffda5f842ea8a4f699c5701c6c7c22bfaf8" } \ No newline at end of file diff --git a/schemas/cache/adagents.json b/schemas/cache/adagents.json index 0097e626..ab0ef5e7 100644 --- a/schemas/cache/adagents.json +++ b/schemas/cache/adagents.json @@ -3,12 +3,12 @@ "description": "Declaration of authorized sales agents for advertising inventory. Hosted at /.well-known/adagents.json on publisher domains. Can either contain the full structure inline or reference an authoritative URL.", "examples": [ { - "$schema": "/schemas/2.6.0/adagents.json", + "$schema": "/schemas/latest/adagents.json", "authoritative_location": "https://cdn.example.com/adagents/v2/adagents.json", "last_updated": "2025-01-15T10:00:00Z" }, { - "$schema": "/schemas/2.6.0/adagents.json", + "$schema": "/schemas/latest/adagents.json", "authorized_agents": [ { "authorization_type": "property_tags", @@ -41,7 +41,7 @@ } }, { - "$schema": "/schemas/2.6.0/adagents.json", + "$schema": "/schemas/latest/adagents.json", "authorized_agents": [ { "authorization_type": "property_tags", @@ -56,6 +56,7 @@ "domain": "meta.com", "email": "adops@meta.com", "name": "Meta Advertising Operations", + "privacy_policy_url": "https://www.meta.com/privacy/policy", "seller_id": "pub-meta-12345", "tag_id": "12345" }, @@ -135,7 +136,7 @@ } }, { - "$schema": "/schemas/2.6.0/adagents.json", + "$schema": "/schemas/latest/adagents.json", "authorized_agents": [ { "authorization_type": "property_tags", @@ -174,7 +175,7 @@ } }, { - "$schema": "/schemas/2.6.0/adagents.json", + "$schema": "/schemas/latest/adagents.json", "authorized_agents": [ { "authorization_type": "publisher_properties", @@ -220,7 +221,7 @@ "last_updated": "2025-01-10T17:00:00Z" }, { - "$schema": "/schemas/2.6.0/adagents.json", + "$schema": "/schemas/latest/adagents.json", "authorized_agents": [ { "authorization_type": "property_tags", @@ -504,6 +505,11 @@ "minLength": 1, "type": "string" }, + "privacy_policy_url": { + "description": "URL to the entity's privacy policy. Used for consumer consent flows when interacting with this sales agent.", + "format": "uri", + "type": "string" + }, "seller_id": { "description": "Seller ID from IAB Tech Lab sellers.json (if applicable)", "maxLength": 255, diff --git a/schemas/cache/content-standards/artifact-webhook-payload.json b/schemas/cache/content-standards/artifact-webhook-payload.json new file mode 100644 index 00000000..5d672d24 --- /dev/null +++ b/schemas/cache/content-standards/artifact-webhook-payload.json @@ -0,0 +1,79 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Payload sent by sales agents to orchestrators when pushing content artifacts for governance validation. Complements get_media_buy_artifacts for push-based artifact delivery.", + "properties": { + "artifacts": { + "description": "Content artifacts from delivered impressions", + "items": { + "properties": { + "artifact": { + "$ref": "artifact.json", + "description": "The content artifact" + }, + "delivered_at": { + "description": "When the impression was delivered (ISO 8601)", + "format": "date-time", + "type": "string" + }, + "impression_id": { + "description": "Optional impression identifier for correlation with delivery reports", + "type": "string" + }, + "package_id": { + "description": "Package within the media buy this artifact relates to", + "type": "string" + } + }, + "required": [ + "artifact", + "delivered_at" + ], + "type": "object" + }, + "type": "array" + }, + "batch_id": { + "description": "Unique identifier for this batch of artifacts. Use for deduplication and acknowledgment.", + "type": "string" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "media_buy_id": { + "description": "Media buy identifier these artifacts belong to", + "type": "string" + }, + "pagination": { + "description": "Pagination info when batching large artifact sets", + "properties": { + "batch_number": { + "description": "Current batch number (1-indexed)", + "type": "integer" + }, + "total_artifacts": { + "description": "Total artifacts in the delivery period", + "type": "integer" + }, + "total_batches": { + "description": "Total batches for this delivery period", + "type": "integer" + } + }, + "type": "object" + }, + "timestamp": { + "description": "When this batch was generated (ISO 8601)", + "format": "date-time", + "type": "string" + } + }, + "required": [ + "media_buy_id", + "batch_id", + "timestamp", + "artifacts" + ], + "title": "Artifact Webhook Payload", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/artifact.json b/schemas/cache/content-standards/artifact.json new file mode 100644 index 00000000..8ee92049 --- /dev/null +++ b/schemas/cache/content-standards/artifact.json @@ -0,0 +1,351 @@ +{ + "$defs": { + "asset_access": { + "description": "Authentication for accessing secured asset URLs", + "oneOf": [ + { + "description": "Bearer token authentication", + "properties": { + "method": { + "const": "bearer_token", + "type": "string" + }, + "token": { + "description": "OAuth2 bearer token for Authorization header", + "type": "string" + } + }, + "required": [ + "method", + "token" + ], + "type": "object" + }, + { + "description": "Service account authentication (GCP, AWS)", + "properties": { + "credentials": { + "additionalProperties": true, + "description": "Service account credentials", + "type": "object" + }, + "method": { + "const": "service_account", + "type": "string" + }, + "provider": { + "description": "Cloud provider", + "enum": [ + "gcp", + "aws" + ], + "type": "string" + } + }, + "required": [ + "method", + "provider" + ], + "type": "object" + }, + { + "description": "Pre-signed URL (credentials embedded in URL)", + "properties": { + "method": { + "const": "signed_url", + "type": "string" + } + }, + "required": [ + "method" + ], + "type": "object" + } + ], + "type": "object" + } + }, + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Content artifact for safety and suitability evaluation. An artifact represents content adjacent to an ad placement - a news article, podcast segment, video chapter, or social post. Artifacts are collections of assets (text, images, video, audio) plus metadata and signals.", + "properties": { + "artifact_id": { + "description": "Identifier for this artifact within the property. The property owner defines the scheme (e.g., 'article_12345', 'episode_42_segment_3', 'post_abc123').", + "type": "string" + }, + "assets": { + "description": "Artifact assets in document flow order - text blocks, images, video, audio", + "items": { + "oneOf": [ + { + "description": "Text block (paragraph, heading, etc.)", + "properties": { + "content": { + "description": "Text content", + "type": "string" + }, + "heading_level": { + "description": "Heading level (1-6), only for role=heading", + "maximum": 6, + "minimum": 1, + "type": "integer" + }, + "language": { + "description": "BCP 47 language tag for this text (e.g., 'en', 'es-MX'). Useful when artifact contains mixed-language content.", + "type": "string" + }, + "role": { + "description": "Role of this text in the document. Use 'title' for the main artifact title, 'description' for summaries.", + "enum": [ + "title", + "paragraph", + "heading", + "caption", + "quote", + "list_item", + "description" + ], + "type": "string" + }, + "type": { + "const": "text", + "type": "string" + } + }, + "required": [ + "type", + "content" + ], + "type": "object" + }, + { + "description": "Image asset", + "properties": { + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "alt_text": { + "description": "Alt text or image description", + "type": "string" + }, + "caption": { + "description": "Image caption", + "type": "string" + }, + "height": { + "description": "Image height in pixels", + "type": "integer" + }, + "type": { + "const": "image", + "type": "string" + }, + "url": { + "description": "Image URL", + "format": "uri", + "type": "string" + }, + "width": { + "description": "Image width in pixels", + "type": "integer" + } + }, + "required": [ + "type", + "url" + ], + "type": "object" + }, + { + "description": "Video asset", + "properties": { + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "description": "Video duration in milliseconds", + "type": "integer" + }, + "thumbnail_url": { + "description": "Video thumbnail URL", + "format": "uri", + "type": "string" + }, + "transcript": { + "description": "Video transcript", + "type": "string" + }, + "transcript_source": { + "description": "How the transcript was generated", + "enum": [ + "original_script", + "subtitles", + "closed_captions", + "dub", + "generated" + ], + "type": "string" + }, + "type": { + "const": "video", + "type": "string" + }, + "url": { + "description": "Video URL", + "format": "uri", + "type": "string" + } + }, + "required": [ + "type", + "url" + ], + "type": "object" + }, + { + "description": "Audio asset", + "properties": { + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "description": "Audio duration in milliseconds", + "type": "integer" + }, + "transcript": { + "description": "Audio transcript", + "type": "string" + }, + "transcript_source": { + "description": "How the transcript was generated", + "enum": [ + "original_script", + "closed_captions", + "generated" + ], + "type": "string" + }, + "type": { + "const": "audio", + "type": "string" + }, + "url": { + "description": "Audio URL", + "format": "uri", + "type": "string" + } + }, + "required": [ + "type", + "url" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "format_id": { + "$ref": "../core/format-id.json", + "description": "Optional reference to a format definition. Uses the same format registry as creative formats." + }, + "identifiers": { + "additionalProperties": true, + "description": "Platform-specific identifiers for this artifact", + "properties": { + "apple_podcast_id": { + "description": "Apple Podcasts ID", + "type": "string" + }, + "podcast_guid": { + "description": "Podcast GUID (from RSS feed)", + "type": "string" + }, + "rss_url": { + "description": "RSS feed URL", + "format": "uri", + "type": "string" + }, + "spotify_show_id": { + "description": "Spotify show ID", + "type": "string" + }, + "youtube_video_id": { + "description": "YouTube video ID", + "type": "string" + } + }, + "type": "object" + }, + "last_update_time": { + "description": "When the artifact was last modified (ISO 8601 format)", + "format": "date-time", + "type": "string" + }, + "metadata": { + "additionalProperties": true, + "description": "Rich metadata extracted from the artifact", + "properties": { + "author": { + "description": "Artifact author name", + "type": "string" + }, + "canonical": { + "description": "Canonical URL", + "format": "uri", + "type": "string" + }, + "json_ld": { + "description": "JSON-LD structured data (schema.org)", + "items": { + "type": "object" + }, + "type": "array" + }, + "keywords": { + "description": "Artifact keywords", + "type": "string" + }, + "open_graph": { + "additionalProperties": true, + "description": "Open Graph protocol metadata", + "type": "object" + }, + "twitter_card": { + "additionalProperties": true, + "description": "Twitter Card metadata", + "type": "object" + } + }, + "type": "object" + }, + "property_id": { + "$ref": "../core/identifier.json", + "description": "Identifier for the property where this artifact appears" + }, + "published_time": { + "description": "When the artifact was published (ISO 8601 format)", + "format": "date-time", + "type": "string" + }, + "url": { + "description": "Optional URL for this artifact (web page, podcast feed, video page). Not all artifacts have URLs (e.g., Instagram content, podcast segments, TV scenes).", + "format": "uri", + "type": "string" + }, + "variant_id": { + "description": "Identifies a specific variant of this artifact. Use for A/B tests, translations, or temporal versions. Examples: 'en', 'es-MX', 'v2', 'headline_test_b'. The combination of artifact_id + variant_id must be unique.", + "type": "string" + } + }, + "required": [ + "property_id", + "artifact_id", + "assets" + ], + "title": "Artifact", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/calibrate-content-request.json b/schemas/cache/content-standards/calibrate-content-request.json new file mode 100644 index 00000000..7154faaf --- /dev/null +++ b/schemas/cache/content-standards/calibrate-content-request.json @@ -0,0 +1,20 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Request parameters for evaluating content during calibration. Multi-turn dialogue is handled at the protocol layer via contextId.", + "properties": { + "artifact": { + "$ref": "artifact.json", + "description": "Artifact to evaluate" + }, + "standards_id": { + "description": "Standards configuration to calibrate against", + "type": "string" + } + }, + "required": [ + "standards_id", + "artifact" + ], + "title": "Calibrate Content Request", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/calibrate-content-response.json b/schemas/cache/content-standards/calibrate-content-response.json new file mode 100644 index 00000000..a1a0f0be --- /dev/null +++ b/schemas/cache/content-standards/calibrate-content-response.json @@ -0,0 +1,89 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Response payload with verdict and detailed explanations for collaborative calibration", + "oneOf": [ + { + "description": "Success response with detailed calibration feedback", + "properties": { + "confidence": { + "description": "Model confidence in the verdict (0-1)", + "maximum": 1, + "minimum": 0, + "type": "number" + }, + "errors": { + "description": "Field must not be present in success response", + "not": {} + }, + "explanation": { + "description": "Detailed natural language explanation of the decision", + "type": "string" + }, + "features": { + "description": "Per-feature breakdown with explanations", + "items": { + "properties": { + "explanation": { + "description": "Human-readable explanation of why this feature passed or failed", + "type": "string" + }, + "feature_id": { + "description": "Which feature was evaluated (e.g., brand_safety, brand_suitability, competitor_adjacency)", + "type": "string" + }, + "status": { + "description": "Evaluation status for this feature", + "enum": [ + "passed", + "failed", + "warning", + "unevaluated" + ], + "type": "string" + } + }, + "required": [ + "feature_id", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "verdict": { + "description": "Overall pass/fail verdict for the content evaluation", + "enum": [ + "pass", + "fail" + ], + "type": "string" + } + }, + "required": [ + "verdict" + ], + "type": "object" + }, + { + "description": "Error response", + "properties": { + "errors": { + "items": { + "$ref": "../core/error.json" + }, + "type": "array" + }, + "verdict": { + "description": "Field must not be present in error response", + "not": {} + } + }, + "required": [ + "errors" + ], + "type": "object" + } + ], + "title": "Calibrate Content Response", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/content-standards.json b/schemas/cache/content-standards/content-standards.json new file mode 100644 index 00000000..ac920a7f --- /dev/null +++ b/schemas/cache/content-standards/content-standards.json @@ -0,0 +1,68 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "A content standards configuration defining brand safety and suitability policies. Standards are scoped by brand, geography, and channel. Multiple standards can be active simultaneously for different scopes.", + "properties": { + "calibration_exemplars": { + "description": "Training/test set to calibrate policy interpretation. Provides concrete examples of pass/fail decisions.", + "properties": { + "fail": { + "description": "Artifacts that fail the content standards", + "items": { + "$ref": "artifact.json" + }, + "type": "array" + }, + "pass": { + "description": "Artifacts that pass the content standards", + "items": { + "$ref": "artifact.json" + }, + "type": "array" + } + }, + "type": "object" + }, + "channels_any": { + "description": "Advertising channels. Standards apply to ANY of the listed channels (OR logic).", + "items": { + "$ref": "../enums/channels.json" + }, + "type": "array" + }, + "countries_all": { + "description": "ISO 3166-1 alpha-2 country codes. Standards apply in ALL listed countries (AND logic).", + "items": { + "type": "string" + }, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "languages_any": { + "description": "BCP 47 language tags (e.g., 'en', 'de', 'fr'). Standards apply to content in ANY of these languages (OR logic). Content in unlisted languages is not covered by these standards.", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + "name": { + "description": "Human-readable name for this standards configuration", + "type": "string" + }, + "policy": { + "description": "Natural language policy describing acceptable and unacceptable content contexts. Used by LLMs and human reviewers to make judgments.", + "type": "string" + }, + "standards_id": { + "description": "Unique identifier for this standards configuration", + "type": "string" + } + }, + "required": [ + "standards_id" + ], + "title": "Content Standards", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/create-content-standards-request.json b/schemas/cache/content-standards/create-content-standards-request.json new file mode 100644 index 00000000..1779d0db --- /dev/null +++ b/schemas/cache/content-standards/create-content-standards-request.json @@ -0,0 +1,136 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Request parameters for creating a new content standards configuration", + "properties": { + "calibration_exemplars": { + "description": "Training/test set to calibrate policy interpretation. Use URL references for pages to be fetched and analyzed, or full artifacts for pre-extracted content.", + "properties": { + "fail": { + "description": "Content that fails the standards", + "items": { + "oneOf": [ + { + "description": "URL reference - specific page to fetch and evaluate", + "properties": { + "language": { + "description": "BCP 47 language tag for content at this URL", + "type": "string" + }, + "type": { + "const": "url", + "description": "Indicates this is a URL reference", + "type": "string" + }, + "value": { + "description": "Full URL to a specific page (e.g., 'https://news.example.com/controversial-article')", + "format": "uri", + "type": "string" + } + }, + "required": [ + "type", + "value" + ], + "type": "object" + }, + { + "$ref": "artifact.json", + "description": "Full artifact with pre-extracted content (text, images, video, audio)" + } + ] + }, + "type": "array" + }, + "pass": { + "description": "Content that passes the standards", + "items": { + "oneOf": [ + { + "description": "URL reference - specific page to fetch and evaluate", + "properties": { + "language": { + "description": "BCP 47 language tag for content at this URL", + "type": "string" + }, + "type": { + "const": "url", + "description": "Indicates this is a URL reference", + "type": "string" + }, + "value": { + "description": "Full URL to a specific page (e.g., 'https://espn.com/nba/story/_/id/12345/lakers-win')", + "format": "uri", + "type": "string" + } + }, + "required": [ + "type", + "value" + ], + "type": "object" + }, + { + "$ref": "artifact.json", + "description": "Full artifact with pre-extracted content (text, images, video, audio)" + } + ] + }, + "type": "array" + } + }, + "type": "object" + }, + "context": { + "$ref": "../core/context.json" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "policy": { + "description": "Natural language policy describing acceptable and unacceptable content contexts. Used by LLMs and human reviewers to make judgments.", + "type": "string" + }, + "scope": { + "description": "Where this standards configuration applies", + "properties": { + "channels_any": { + "description": "Advertising channels. Standards apply to ANY of the listed channels (OR logic).", + "items": { + "$ref": "../enums/channels.json" + }, + "type": "array" + }, + "countries_all": { + "description": "ISO 3166-1 alpha-2 country codes. Standards apply in ALL listed countries (AND logic).", + "items": { + "type": "string" + }, + "type": "array" + }, + "description": { + "description": "Human-readable description of this scope", + "type": "string" + }, + "languages_any": { + "description": "BCP 47 language tags (e.g., 'en', 'de', 'fr'). Standards apply to content in ANY of these languages (OR logic). Content in unlisted languages is not covered by these standards.", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "languages_any" + ], + "type": "object" + } + }, + "required": [ + "scope", + "policy" + ], + "title": "Create Content Standards Request", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/create-content-standards-response.json b/schemas/cache/content-standards/create-content-standards-response.json new file mode 100644 index 00000000..ccc57f40 --- /dev/null +++ b/schemas/cache/content-standards/create-content-standards-response.json @@ -0,0 +1,60 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Response payload for creating a content standards configuration", + "oneOf": [ + { + "description": "Success response - returns the created standards identifier", + "properties": { + "context": { + "$ref": "../core/context.json" + }, + "errors": { + "description": "Field must not be present in success response", + "not": {} + }, + "ext": { + "$ref": "../core/ext.json" + }, + "standards_id": { + "description": "Unique identifier for the created standards configuration", + "type": "string" + } + }, + "required": [ + "standards_id" + ], + "type": "object" + }, + { + "description": "Error response", + "properties": { + "conflicting_standards_id": { + "description": "If the error is a scope conflict, the ID of the existing standards that conflict", + "type": "string" + }, + "context": { + "$ref": "../core/context.json" + }, + "errors": { + "items": { + "$ref": "../core/error.json" + }, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "standards_id": { + "description": "Field must not be present in error response", + "not": {} + } + }, + "required": [ + "errors" + ], + "type": "object" + } + ], + "title": "Create Content Standards Response", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/get-content-standards-request.json b/schemas/cache/content-standards/get-content-standards-request.json new file mode 100644 index 00000000..4ee7f59e --- /dev/null +++ b/schemas/cache/content-standards/get-content-standards-request.json @@ -0,0 +1,21 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Request parameters for retrieving content safety policies", + "properties": { + "context": { + "$ref": "../core/context.json" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "standards_id": { + "description": "Identifier for the standards configuration to retrieve", + "type": "string" + } + }, + "required": [ + "standards_id" + ], + "title": "Get Content Standards Request", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/get-content-standards-response.json b/schemas/cache/content-standards/get-content-standards-response.json new file mode 100644 index 00000000..5aa29b9e --- /dev/null +++ b/schemas/cache/content-standards/get-content-standards-response.json @@ -0,0 +1,51 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Response payload with content safety policies", + "oneOf": [ + { + "allOf": [ + { + "$ref": "content-standards.json" + } + ], + "description": "Success response - returns the content standards configuration", + "properties": { + "context": { + "$ref": "../core/context.json" + }, + "errors": { + "description": "Field must not be present in success response", + "not": {} + } + }, + "type": "object" + }, + { + "description": "Error response", + "properties": { + "context": { + "$ref": "../core/context.json" + }, + "errors": { + "items": { + "$ref": "../core/error.json" + }, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "standards_id": { + "description": "Field must not be present in error response", + "not": {} + } + }, + "required": [ + "errors" + ], + "type": "object" + } + ], + "title": "Get Content Standards Response", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/get-media-buy-artifacts-request.json b/schemas/cache/content-standards/get-media-buy-artifacts-request.json new file mode 100644 index 00000000..0ad47936 --- /dev/null +++ b/schemas/cache/content-standards/get-media-buy-artifacts-request.json @@ -0,0 +1,77 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Request parameters for retrieving content artifacts from a media buy for validation", + "properties": { + "context": { + "$ref": "../core/context.json" + }, + "cursor": { + "description": "Pagination cursor for fetching subsequent pages", + "type": "string" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "limit": { + "default": 1000, + "description": "Maximum artifacts to return per request", + "maximum": 10000, + "minimum": 1, + "type": "integer" + }, + "media_buy_id": { + "description": "Media buy to get artifacts from", + "type": "string" + }, + "package_ids": { + "description": "Filter to specific packages within the media buy", + "items": { + "type": "string" + }, + "type": "array" + }, + "sampling": { + "description": "Sampling parameters. Defaults to the sampling rate agreed in the media buy.", + "properties": { + "method": { + "description": "How to select the sample", + "enum": [ + "random", + "stratified", + "recent", + "failures_only" + ], + "type": "string" + }, + "rate": { + "description": "Sampling rate (0-1). 1.0 = all deliveries, 0.25 = 25% sample.", + "maximum": 1, + "minimum": 0, + "type": "number" + } + }, + "type": "object" + }, + "time_range": { + "description": "Filter to specific time period", + "properties": { + "end": { + "description": "End of time range (exclusive)", + "format": "date-time", + "type": "string" + }, + "start": { + "description": "Start of time range (inclusive)", + "format": "date-time", + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "media_buy_id" + ], + "title": "Get Media Buy Artifacts Request", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/get-media-buy-artifacts-response.json b/schemas/cache/content-standards/get-media-buy-artifacts-response.json new file mode 100644 index 00000000..14af89f5 --- /dev/null +++ b/schemas/cache/content-standards/get-media-buy-artifacts-response.json @@ -0,0 +1,160 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Response containing content artifacts from a media buy for validation", + "oneOf": [ + { + "description": "Success response with artifacts", + "properties": { + "artifacts": { + "description": "Delivery records with full artifact content", + "items": { + "properties": { + "artifact": { + "$ref": "artifact.json", + "description": "Full artifact with content assets" + }, + "brand_context": { + "description": "Brand information for policy evaluation. Schema TBD - placeholder for brand identifiers.", + "properties": { + "brand_id": { + "description": "Brand identifier", + "type": "string" + }, + "sku_id": { + "description": "Product/SKU identifier if applicable", + "type": "string" + } + }, + "type": "object" + }, + "channel": { + "description": "Channel type (e.g., display, video, audio, social)", + "type": "string" + }, + "country": { + "description": "ISO 3166-1 alpha-2 country code where delivery occurred", + "type": "string" + }, + "local_verdict": { + "description": "Seller's local model verdict for this artifact", + "enum": [ + "pass", + "fail", + "unevaluated" + ], + "type": "string" + }, + "package_id": { + "description": "Which package this delivery belongs to", + "type": "string" + }, + "record_id": { + "description": "Unique identifier for this delivery record", + "type": "string" + }, + "timestamp": { + "description": "When the delivery occurred", + "format": "date-time", + "type": "string" + } + }, + "required": [ + "record_id", + "artifact" + ], + "type": "object" + }, + "type": "array" + }, + "context": { + "$ref": "../core/context.json" + }, + "errors": { + "description": "Field must not be present in success response", + "not": {} + }, + "ext": { + "$ref": "../core/ext.json" + }, + "media_buy_id": { + "description": "Media buy these artifacts belong to", + "type": "string" + }, + "pagination": { + "description": "Pagination information for large result sets", + "properties": { + "cursor": { + "description": "Cursor for fetching the next page", + "type": "string" + }, + "has_more": { + "description": "Whether more results are available", + "type": "boolean" + } + }, + "type": "object" + }, + "sampling_info": { + "description": "Information about how the sample was generated", + "properties": { + "effective_rate": { + "description": "Actual sampling rate achieved", + "type": "number" + }, + "method": { + "description": "Sampling method used", + "enum": [ + "random", + "stratified", + "recent", + "failures_only" + ], + "type": "string" + }, + "sampled_count": { + "description": "Number of artifacts in this response", + "type": "integer" + }, + "total_deliveries": { + "description": "Total deliveries in the time range", + "type": "integer" + } + }, + "type": "object" + } + }, + "required": [ + "media_buy_id", + "artifacts" + ], + "type": "object" + }, + { + "description": "Error response", + "properties": { + "context": { + "$ref": "../core/context.json" + }, + "errors": { + "items": { + "$ref": "../core/error.json" + }, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "media_buy_id": { + "description": "Field must not be present in error response", + "not": {} + } + }, + "required": [ + "errors" + ], + "type": "object" + } + ], + "title": "Get Media Buy Artifacts Response", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/list-content-standards-request.json b/schemas/cache/content-standards/list-content-standards-request.json new file mode 100644 index 00000000..1fd64d41 --- /dev/null +++ b/schemas/cache/content-standards/list-content-standards-request.json @@ -0,0 +1,36 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Request parameters for listing content standards configurations", + "properties": { + "channels": { + "description": "Filter by channel", + "items": { + "$ref": "../enums/channels.json" + }, + "type": "array" + }, + "context": { + "$ref": "../core/context.json" + }, + "countries": { + "description": "Filter by ISO 3166-1 alpha-2 country codes", + "items": { + "type": "string" + }, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "languages": { + "description": "Filter by BCP 47 language tags", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "title": "List Content Standards Request", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/list-content-standards-response.json b/schemas/cache/content-standards/list-content-standards-response.json new file mode 100644 index 00000000..e826e00d --- /dev/null +++ b/schemas/cache/content-standards/list-content-standards-response.json @@ -0,0 +1,59 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Response payload with list of content standards configurations", + "oneOf": [ + { + "description": "Success response - returns array of content standards", + "properties": { + "context": { + "$ref": "../core/context.json" + }, + "errors": { + "description": "Field must not be present in success response", + "not": {} + }, + "ext": { + "$ref": "../core/ext.json" + }, + "standards": { + "description": "Array of content standards configurations matching the filter criteria", + "items": { + "$ref": "content-standards.json" + }, + "type": "array" + } + }, + "required": [ + "standards" + ], + "type": "object" + }, + { + "description": "Error response", + "properties": { + "context": { + "$ref": "../core/context.json" + }, + "errors": { + "items": { + "$ref": "../core/error.json" + }, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "standards": { + "description": "Field must not be present in error response", + "not": {} + } + }, + "required": [ + "errors" + ], + "type": "object" + } + ], + "title": "List Content Standards Response", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/update-content-standards-request.json b/schemas/cache/content-standards/update-content-standards-request.json new file mode 100644 index 00000000..91db59d5 --- /dev/null +++ b/schemas/cache/content-standards/update-content-standards-request.json @@ -0,0 +1,136 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Request parameters for updating an existing content standards configuration. Creates a new version.", + "properties": { + "calibration_exemplars": { + "description": "Updated training/test set to calibrate policy interpretation. Use URL references for pages to be fetched and analyzed, or full artifacts for pre-extracted content.", + "properties": { + "fail": { + "description": "Content that fails the standards", + "items": { + "oneOf": [ + { + "description": "URL reference - specific page to fetch and evaluate", + "properties": { + "language": { + "description": "BCP 47 language tag for content at this URL", + "type": "string" + }, + "type": { + "const": "url", + "description": "Indicates this is a URL reference", + "type": "string" + }, + "value": { + "description": "Full URL to a specific page (e.g., 'https://news.example.com/controversial-article')", + "format": "uri", + "type": "string" + } + }, + "required": [ + "type", + "value" + ], + "type": "object" + }, + { + "$ref": "artifact.json", + "description": "Full artifact with pre-extracted content (text, images, video, audio)" + } + ] + }, + "type": "array" + }, + "pass": { + "description": "Content that passes the standards", + "items": { + "oneOf": [ + { + "description": "URL reference - specific page to fetch and evaluate", + "properties": { + "language": { + "description": "BCP 47 language tag for content at this URL", + "type": "string" + }, + "type": { + "const": "url", + "description": "Indicates this is a URL reference", + "type": "string" + }, + "value": { + "description": "Full URL to a specific page (e.g., 'https://espn.com/nba/story/_/id/12345/lakers-win')", + "format": "uri", + "type": "string" + } + }, + "required": [ + "type", + "value" + ], + "type": "object" + }, + { + "$ref": "artifact.json", + "description": "Full artifact with pre-extracted content (text, images, video, audio)" + } + ] + }, + "type": "array" + } + }, + "type": "object" + }, + "context": { + "$ref": "../core/context.json" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "policy": { + "description": "Updated natural language policy describing acceptable and unacceptable content contexts.", + "type": "string" + }, + "scope": { + "description": "Updated scope for where this standards configuration applies", + "properties": { + "channels_any": { + "description": "Advertising channels. Standards apply to ANY of the listed channels (OR logic).", + "items": { + "$ref": "../enums/channels.json" + }, + "type": "array" + }, + "countries_all": { + "description": "ISO 3166-1 alpha-2 country codes. Standards apply in ALL listed countries (AND logic).", + "items": { + "type": "string" + }, + "type": "array" + }, + "description": { + "description": "Human-readable description of this scope", + "type": "string" + }, + "languages_any": { + "description": "BCP 47 language tags (e.g., 'en', 'de', 'fr'). Standards apply to content in ANY of these languages (OR logic). Content in unlisted languages is not covered by these standards.", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + }, + "type": "object" + }, + "standards_id": { + "description": "ID of the standards configuration to update", + "type": "string" + } + }, + "required": [ + "standards_id" + ], + "title": "Update Content Standards Request", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/update-content-standards-response.json b/schemas/cache/content-standards/update-content-standards-response.json new file mode 100644 index 00000000..3eb265d6 --- /dev/null +++ b/schemas/cache/content-standards/update-content-standards-response.json @@ -0,0 +1,44 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Response from updating a content standards configuration", + "properties": { + "conflicting_standards_id": { + "description": "If scope change conflicts with another configuration, the ID of the conflicting standards", + "type": "string" + }, + "context": { + "$ref": "../core/context.json" + }, + "errors": { + "description": "Errors that occurred during the update", + "items": { + "properties": { + "code": { + "description": "Error code (e.g., STANDARDS_NOT_FOUND, SCOPE_CONFLICT)", + "type": "string" + }, + "message": { + "description": "Human-readable error message", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "standards_id": { + "description": "ID of the updated standards configuration", + "type": "string" + } + }, + "title": "Update Content Standards Response", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/validate-content-delivery-request.json b/schemas/cache/content-standards/validate-content-delivery-request.json new file mode 100644 index 00000000..48d85355 --- /dev/null +++ b/schemas/cache/content-standards/validate-content-delivery-request.json @@ -0,0 +1,87 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Request parameters for batch validating delivery records against content safety policies", + "properties": { + "context": { + "$ref": "../core/context.json" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "feature_ids": { + "description": "Specific features to evaluate (defaults to all)", + "items": { + "type": "string" + }, + "type": "array" + }, + "include_passed": { + "default": true, + "description": "Include passed records in results", + "type": "boolean" + }, + "records": { + "description": "Delivery records to validate (max 10,000)", + "items": { + "properties": { + "artifact": { + "$ref": "artifact.json", + "description": "Artifact where ad was delivered" + }, + "brand_context": { + "description": "Brand information for policy evaluation. Schema TBD - placeholder for brand identifiers.", + "properties": { + "brand_id": { + "description": "Brand identifier", + "type": "string" + }, + "sku_id": { + "description": "Product/SKU identifier if applicable", + "type": "string" + } + }, + "type": "object" + }, + "channel": { + "description": "Channel type (e.g., display, video, audio, social)", + "type": "string" + }, + "country": { + "description": "ISO 3166-1 alpha-2 country code where delivery occurred", + "type": "string" + }, + "media_buy_id": { + "description": "Media buy this record belongs to (when batching across multiple buys)", + "type": "string" + }, + "record_id": { + "description": "Unique identifier for this delivery record", + "type": "string" + }, + "timestamp": { + "description": "When the delivery occurred", + "format": "date-time", + "type": "string" + } + }, + "required": [ + "record_id", + "artifact" + ], + "type": "object" + }, + "maxItems": 10000, + "type": "array" + }, + "standards_id": { + "description": "Standards configuration to validate against", + "type": "string" + } + }, + "required": [ + "standards_id", + "records" + ], + "title": "Validate Content Delivery Request", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/content-standards/validate-content-delivery-response.json b/schemas/cache/content-standards/validate-content-delivery-response.json new file mode 100644 index 00000000..864b258a --- /dev/null +++ b/schemas/cache/content-standards/validate-content-delivery-response.json @@ -0,0 +1,131 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Response payload with per-record verdicts and optional feature breakdown", + "oneOf": [ + { + "description": "Success response", + "properties": { + "context": { + "$ref": "../core/context.json" + }, + "errors": { + "description": "Field must not be present in success response", + "not": {} + }, + "ext": { + "$ref": "../core/ext.json" + }, + "results": { + "description": "Per-record evaluation results", + "items": { + "properties": { + "features": { + "description": "Optional feature-level breakdown", + "items": { + "properties": { + "feature_id": { + "type": "string" + }, + "message": { + "type": "string" + }, + "rule_id": { + "description": "Which rule triggered this result (e.g., GARM category, Scope3 standard)", + "type": "string" + }, + "status": { + "enum": [ + "passed", + "failed", + "warning", + "unevaluated" + ], + "type": "string" + }, + "value": {} + }, + "required": [ + "feature_id", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "record_id": { + "description": "Which delivery record was evaluated", + "type": "string" + }, + "verdict": { + "description": "Overall pass/fail verdict for this record", + "enum": [ + "pass", + "fail" + ], + "type": "string" + } + }, + "required": [ + "record_id", + "verdict" + ], + "type": "object" + }, + "type": "array" + }, + "summary": { + "description": "Summary counts across all records", + "properties": { + "failed_records": { + "type": "integer" + }, + "passed_records": { + "type": "integer" + }, + "total_records": { + "type": "integer" + } + }, + "required": [ + "total_records", + "passed_records", + "failed_records" + ], + "type": "object" + } + }, + "required": [ + "summary", + "results" + ], + "type": "object" + }, + { + "description": "Error response", + "properties": { + "context": { + "$ref": "../core/context.json" + }, + "errors": { + "items": { + "$ref": "../core/error.json" + }, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "summary": { + "description": "Field must not be present in error response", + "not": {} + } + }, + "required": [ + "errors" + ], + "type": "object" + } + ], + "title": "Validate Content Delivery Response", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/core/brand-manifest.json b/schemas/cache/core/brand-manifest.json index 28fa3c34..df1a454d 100644 --- a/schemas/cache/core/brand-manifest.json +++ b/schemas/cache/core/brand-manifest.json @@ -95,6 +95,7 @@ } ], "name": "ACME Corporation", + "privacy_policy_url": "https://acmecorp.com/privacy", "product_catalog": { "categories": [ "electronics/computers", @@ -111,6 +112,27 @@ "url": "https://acmecorp.com" }, "description": "Full brand manifest with all fields" + }, + { + "data": { + "name": "Shop Example", + "privacy_policy_url": "https://shopexample.com/privacy", + "product_catalog": { + "agentic_checkout": { + "endpoint": "https://api.shopexample.com/checkout_sessions", + "spec": "openai_agentic_checkout_v1", + "supported_payment_providers": [ + "stripe", + "adyen" + ] + }, + "feed_format": "openai_product_feed", + "feed_url": "https://shopexample.com/products.jsonl.gz", + "update_frequency": "daily" + }, + "url": "https://shopexample.com" + }, + "description": "E-commerce brand with OpenAI product feed and agentic checkout" } ], "properties": { @@ -182,6 +204,25 @@ }, "type": "array" }, + "avatar": { + "description": "Brand avatar configuration for visual conversational experiences", + "properties": { + "avatar_id": { + "description": "Provider-specific avatar identifier", + "type": "string" + }, + "provider": { + "description": "Avatar provider (e.g., 'd-id', 'heygen', 'synthesia')", + "type": "string" + }, + "settings": { + "additionalProperties": true, + "description": "Provider-specific avatar settings", + "type": "object" + } + }, + "type": "object" + }, "colors": { "description": "Brand color palette", "properties": { @@ -335,10 +376,44 @@ "description": "Brand or business name", "type": "string" }, + "privacy_policy_url": { + "description": "URL to the brand's privacy policy. Used for consumer consent flows when personal data may be shared with the advertiser. AI platforms can use this to present explicit privacy choices to users before data handoff.", + "format": "uri", + "type": "string" + }, "product_catalog": { "additionalProperties": true, "description": "Product catalog information for e-commerce advertisers. Enables SKU-level creative generation and product selection.", "properties": { + "agentic_checkout": { + "description": "Agentic checkout endpoint configuration. Enables AI agents to complete purchases on behalf of users through a structured checkout API.", + "properties": { + "endpoint": { + "description": "Base URL for checkout session API (e.g., https://merchant.com/api/checkout_sessions)", + "format": "uri", + "type": "string" + }, + "spec": { + "description": "Checkout API specification implemented by the endpoint", + "enum": [ + "openai_agentic_checkout_v1" + ], + "type": "string" + }, + "supported_payment_providers": { + "description": "Payment providers supported by this checkout endpoint", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "endpoint", + "spec" + ], + "type": "object" + }, "categories": { "description": "Product categories available in the catalog (for filtering)", "items": { @@ -348,10 +423,11 @@ }, "feed_format": { "default": "google_merchant_center", - "description": "Format of the product feed", + "description": "Format of the product feed. Use 'openai_product_feed' for feeds conforming to the OpenAI Commerce Product Feed specification.", "enum": [ "google_merchant_center", "facebook_catalog", + "openai_product_feed", "custom" ], "type": "string" @@ -398,6 +474,25 @@ "description": "Primary brand URL for context and asset discovery. Creative agents can infer brand information from this URL.", "format": "uri", "type": "string" + }, + "voice": { + "description": "Brand voice configuration for audio/conversational experiences", + "properties": { + "provider": { + "description": "TTS provider (e.g., 'elevenlabs', 'openai', 'amazon_polly')", + "type": "string" + }, + "settings": { + "additionalProperties": true, + "description": "Provider-specific voice settings (speed, pitch, etc.)", + "type": "object" + }, + "voice_id": { + "description": "Provider-specific voice identifier", + "type": "string" + } + }, + "type": "object" } }, "required": [ diff --git a/schemas/cache/core/creative-asset.json b/schemas/cache/core/creative-asset.json index ae5dfc6d..f179b0ab 100644 --- a/schemas/cache/core/creative-asset.json +++ b/schemas/cache/core/creative-asset.json @@ -3,10 +3,6 @@ "additionalProperties": true, "description": "Creative asset for upload to library - supports static assets, generative formats, and third-party snippets", "properties": { - "approved": { - "description": "For generative creatives: set to true to approve and finalize, false to request regeneration with updated assets/message. Omit for non-generative creatives.", - "type": "boolean" - }, "assets": { "additionalProperties": true, "description": "Assets required by the format, keyed by asset_role", @@ -99,6 +95,10 @@ "minItems": 1, "type": "array" }, + "status": { + "$ref": "../enums/creative-status.json", + "description": "For generative creatives: set to 'approved' to finalize, 'rejected' to request regeneration with updated assets/message. Omit for non-generative creatives (system will set based on processing state)." + }, "tags": { "description": "User-defined tags for organization and searchability", "items": { diff --git a/schemas/cache/core/creative-filters.json b/schemas/cache/core/creative-filters.json index 2dad375d..05642391 100644 --- a/schemas/cache/core/creative-filters.json +++ b/schemas/cache/core/creative-filters.json @@ -1,12 +1,8 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, - "description": "Filter criteria for querying creative assets from the centralized library", + "description": "Filter criteria for querying creative assets from the centralized library. By default, archived creatives are excluded from results. To include archived creatives, explicitly filter by status='archived' or include 'archived' in the statuses array.", "properties": { - "assigned_to_package": { - "description": "Filter creatives assigned to this specific package", - "type": "string" - }, "assigned_to_packages": { "description": "Filter creatives assigned to any of these packages", "items": { @@ -39,12 +35,8 @@ "maxItems": 100, "type": "array" }, - "format": { - "description": "Filter by creative format type (e.g., video, audio, display)", - "type": "string" - }, "formats": { - "description": "Filter by multiple creative format types", + "description": "Filter by creative format types (e.g., video, audio, display)", "items": { "type": "string" }, @@ -65,12 +57,8 @@ "description": "Filter by creative names containing this text (case-insensitive)", "type": "string" }, - "status": { - "$ref": "../enums/creative-status.json", - "description": "Filter by creative approval status" - }, "statuses": { - "description": "Filter by multiple creative statuses", + "description": "Filter by creative approval statuses", "items": { "$ref": "../enums/creative-status.json" }, diff --git a/schemas/cache/core/media-buy-features.json b/schemas/cache/core/media-buy-features.json new file mode 100644 index 00000000..fe3a6484 --- /dev/null +++ b/schemas/cache/core/media-buy-features.json @@ -0,0 +1,23 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": { + "type": "boolean" + }, + "description": "Optional media-buy protocol features. Used in capability declarations (seller declares support) and product filters (buyer requires support). If a seller declares a feature as true, they MUST honor requests using that feature.", + "properties": { + "content_standards": { + "description": "Full support for content_standards configuration including sampling rates and category filtering", + "type": "boolean" + }, + "inline_creative_management": { + "description": "Supports creatives provided inline in create_media_buy requests", + "type": "boolean" + }, + "property_list_filtering": { + "description": "Honors property_list parameter in get_products to filter results to buyer-approved properties", + "type": "boolean" + } + }, + "title": "Media Buy Features", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/core/offering.json b/schemas/cache/core/offering.json new file mode 100644 index 00000000..da2be5fa --- /dev/null +++ b/schemas/cache/core/offering.json @@ -0,0 +1,150 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "A promotable offering from a brand. Can represent a campaign, product promotion, service, or any other thing the brand wants to make available. Offerings can be promoted via traditional creatives (using portfolio_ref or assets) or conversational SI experiences (via si_agent_url at the promoted-offerings level).", + "examples": [ + { + "data": { + "categories": [ + "measurement", + "sustainability" + ], + "checkout_url": "https://scope3.com/signup", + "description": "Try our carbon measurement platform free for 30 days", + "keywords": [ + "carbon", + "sustainability", + "measurement", + "emissions" + ], + "name": "Free 30-day trial", + "offering_id": "q1-2025-trial", + "tagline": "Start measuring your digital carbon footprint today", + "valid_from": "2025-01-01T00:00:00Z", + "valid_to": "2025-03-31T23:59:59Z" + }, + "description": "Time-limited promotional offer with checkout" + }, + { + "data": { + "categories": [ + "programmatic", + "dsp" + ], + "description": "Full-featured demand-side platform for enterprise advertisers", + "keywords": [ + "dsp", + "programmatic", + "rtb", + "ctv" + ], + "landing_url": "https://thetradedesk.com/enterprise", + "name": "Enterprise DSP Platform", + "offering_id": "enterprise-dsp" + }, + "description": "Product offering with landing page" + }, + { + "data": { + "description": "Up to 50% off summer collection", + "landing_url": "https://brand.com/summer-sale", + "name": "Summer Sale", + "offering_id": "summer-sale-2025", + "portfolio_ref": "https://brand.com/portfolios/summer-2025.json", + "valid_from": "2025-06-01T00:00:00Z", + "valid_to": "2025-08-31T23:59:59Z" + }, + "description": "Offering with creative portfolio" + }, + { + "data": { + "assets": [ + { + "asset_id": "launch-hero", + "asset_type": "image", + "url": "https://cdn.brand.com/launch-hero.jpg" + } + ], + "description": "Introducing our latest innovation", + "name": "New Product Launch", + "offering_id": "product-launch" + }, + "description": "Offering with inline assets" + } + ], + "properties": { + "assets": { + "description": "Assets specific to this offering (images, videos, copy)", + "items": { + "additionalProperties": true, + "description": "Asset definition using standard asset structure", + "type": "object" + }, + "type": "array" + }, + "categories": { + "description": "Categories this offering belongs to (e.g., 'measurement', 'identity', 'programmatic')", + "items": { + "type": "string" + }, + "type": "array" + }, + "checkout_url": { + "description": "URL for checkout/purchase flow when the brand doesn't support agentic checkout.", + "format": "uri", + "type": "string" + }, + "description": { + "description": "Description of what's being offered", + "type": "string" + }, + "ext": { + "$ref": "ext.json" + }, + "keywords": { + "description": "Keywords for matching this offering to user intent. Hosts use these for retrieval/relevance scoring.", + "items": { + "type": "string" + }, + "type": "array" + }, + "landing_url": { + "description": "Landing page URL for this offering.", + "format": "uri", + "type": "string" + }, + "name": { + "description": "Human-readable offering name (e.g., 'Winter Sale', 'Free Trial', 'Enterprise Platform')", + "type": "string" + }, + "offering_id": { + "description": "Unique identifier for this offering. Used by hosts to reference specific offerings in si_get_offering calls.", + "type": "string" + }, + "portfolio_ref": { + "description": "Reference to a creative portfolio for this offering. Portfolios contain organized creative assets across formats, enabling consistent ad delivery for this specific offering.", + "format": "uri", + "type": "string" + }, + "tagline": { + "description": "Short promotional tagline for the offering", + "type": "string" + }, + "valid_from": { + "description": "When the offering becomes available. If not specified, offering is immediately available.", + "format": "date-time", + "type": "string" + }, + "valid_to": { + "description": "When the offering expires. If not specified, offering has no expiration.", + "format": "date-time", + "type": "string" + } + }, + "required": [ + "offering_id", + "name" + ], + "title": "Offering", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/core/product-allocation.json b/schemas/cache/core/product-allocation.json new file mode 100644 index 00000000..275c5463 --- /dev/null +++ b/schemas/cache/core/product-allocation.json @@ -0,0 +1,46 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "A budget allocation for a specific product within a proposal. Percentages across all allocations in a proposal should sum to 100.", + "properties": { + "allocation_percentage": { + "description": "Percentage of total budget allocated to this product (0-100)", + "maximum": 100, + "minimum": 0, + "type": "number" + }, + "ext": { + "$ref": "ext.json" + }, + "pricing_option_id": { + "description": "Recommended pricing option ID from the product's pricing_options array", + "type": "string" + }, + "product_id": { + "description": "ID of the product (must reference a product in the products array)", + "type": "string" + }, + "rationale": { + "description": "Explanation of why this product and allocation are recommended", + "type": "string" + }, + "sequence": { + "description": "Optional ordering hint for multi-line-item plans (1-based)", + "minimum": 1, + "type": "integer" + }, + "tags": { + "description": "Categorical tags for this allocation (e.g., 'desktop', 'german', 'mobile') - useful for grouping/filtering allocations by dimension", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "product_id", + "allocation_percentage" + ], + "title": "Product Allocation", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/core/product-filters.json b/schemas/cache/core/product-filters.json index 2104a47c..3ea939de 100644 --- a/schemas/cache/core/product-filters.json +++ b/schemas/cache/core/product-filters.json @@ -48,7 +48,7 @@ "type": "array" }, "countries": { - "description": "Filter by target countries using ISO 3166-1 alpha-2 country codes (e.g., ['US', 'CA', 'GB'])", + "description": "Filter by country coverage using ISO 3166-1 alpha-2 codes (e.g., ['US', 'CA', 'GB']). Works for all inventory types.", "items": { "pattern": "^[A-Z]{2}$", "type": "string" @@ -81,11 +81,74 @@ "description": "Filter for fixed price vs auction products", "type": "boolean" }, + "metros": { + "description": "Filter by metro coverage for locally-bound inventory (radio, DOOH, local TV). Use when products have DMA/metro-specific coverage. For digital inventory where products have broad coverage, use required_geo_targeting instead to filter by seller capability.", + "items": { + "additionalProperties": false, + "properties": { + "code": { + "description": "Metro code within the system (e.g., '501' for NYC DMA)", + "type": "string" + }, + "system": { + "$ref": "../enums/metro-system.json", + "description": "Metro classification system" + } + }, + "required": [ + "system", + "code" + ], + "type": "object" + }, + "type": "array" + }, "min_exposures": { "description": "Minimum exposures/impressions needed for measurement validity", "minimum": 1, "type": "integer" }, + "regions": { + "description": "Filter by region coverage using ISO 3166-2 codes (e.g., ['US-NY', 'US-CA', 'GB-SCT']). Use for locally-bound inventory (regional OOH, local TV) where products have region-specific coverage.", + "items": { + "pattern": "^[A-Z]{2}-[A-Z0-9]+$", + "type": "string" + }, + "type": "array" + }, + "required_axe_integrations": { + "description": "Filter to products executable through specific agentic ad exchanges. URLs are canonical identifiers.", + "items": { + "format": "uri", + "type": "string" + }, + "type": "array" + }, + "required_features": { + "$ref": "media-buy-features.json", + "description": "Filter to products from sellers supporting specific protocol features. Only features set to true are used for filtering." + }, + "required_geo_targeting": { + "description": "Filter to products from sellers supporting specific geo targeting capabilities. Each entry specifies a targeting level (country, region, metro, postal_area) and optionally a system for levels that have multiple classification systems.", + "items": { + "additionalProperties": false, + "properties": { + "level": { + "$ref": "../enums/geo-level.json", + "description": "Geographic targeting level (country, region, metro, postal_area)" + }, + "system": { + "description": "Classification system within the level. Required for metro (e.g., 'nielsen_dma') and postal_area (e.g., 'us_zip'). Not applicable for country/region which use ISO standards.", + "type": "string" + } + }, + "required": [ + "level" + ], + "type": "object" + }, + "type": "array" + }, "standard_formats_only": { "description": "Only return products accepting IAB standard formats", "type": "boolean" diff --git a/schemas/cache/core/promoted-offerings.json b/schemas/cache/core/promoted-offerings.json index d956dce4..7513c36d 100644 --- a/schemas/cache/core/promoted-offerings.json +++ b/schemas/cache/core/promoted-offerings.json @@ -1,28 +1,70 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, - "description": "Complete offering specification combining brand manifest, product selectors, and asset filters. Provides all context needed for creative generation about what is being promoted.", + "description": "Complete offering specification combining brand manifest, product selectors, and optional SI agent endpoint. Provides all context needed for creative generation and/or conversational experiences about what is being promoted. When si_agent_url is present, hosts can connect users to conversational experiences about any of the offerings.", "examples": [ { - "asset_selectors": { - "asset_types": [ - "image", - "video" + "data": { + "asset_selectors": { + "asset_types": [ + "image", + "video" + ], + "tags": [ + "holiday" + ] + }, + "brand_manifest": { + "name": "Brand Name", + "url": "https://brand.com" + }, + "product_selectors": { + "manifest_skus": [ + "SKU-123", + "SKU-456" + ] + } + }, + "description": "Traditional creative offering (no SI)" + }, + { + "data": { + "brand_manifest": "https://brand.com/manifest.json", + "offerings": [ + { + "checkout_url": "https://brand.com/signup", + "description": "Try our platform free for 30 days", + "name": "Free 30-day trial", + "offering_id": "q1-2025-trial", + "valid_from": "2025-01-01T00:00:00Z", + "valid_to": "2025-03-31T23:59:59Z" + }, + { + "description": "Our flagship enterprise solution", + "landing_url": "https://brand.com/enterprise", + "name": "Enterprise Platform", + "offering_id": "standard-product" + } ], - "tags": [ - "holiday" - ] + "si_agent_url": "https://agent.brand.com/mcp" }, - "brand_manifest": { - "name": "Brand Name", - "url": "https://brand.com" + "description": "Offerings with SI agent for conversational experiences" + }, + { + "data": { + "brand_manifest": "https://brand.com/manifest.json", + "offerings": [ + { + "description": "Up to 50% off summer collection", + "landing_url": "https://brand.com/summer", + "name": "Summer Sale", + "offering_id": "summer-campaign", + "portfolio_ref": "https://brand.com/portfolios/summer-2025.json" + } + ], + "si_agent_url": "https://agent.brand.com/mcp" }, - "product_selectors": { - "manifest_skus": [ - "SKU-123", - "SKU-456" - ] - } + "description": "Offerings with both creatives and SI" } ], "properties": { @@ -72,38 +114,20 @@ "description": "Brand information manifest containing assets, themes, and guidelines. Can be provided inline or as a URL reference to a hosted manifest." }, "offerings": { - "description": "Inline offerings for campaigns without a product catalog. Each offering has a name, description, and associated assets.", + "description": "Offerings available for promotion. Each offering can include creative assets (via portfolio_ref or inline assets) for traditional ads. When si_agent_url is set at the parent level, hosts can offer conversational experiences about any of these offerings.", "items": { - "additionalProperties": true, - "properties": { - "assets": { - "description": "Assets specific to this offering", - "items": { - "additionalProperties": true, - "description": "Asset definition using standard asset structure", - "type": "object" - }, - "type": "array" - }, - "description": { - "description": "Description of what's being offered", - "type": "string" - }, - "name": { - "description": "Offering name (e.g., 'Winter Sale', 'New Product Launch')", - "type": "string" - } - }, - "required": [ - "name" - ], - "type": "object" + "$ref": "offering.json" }, "type": "array" }, "product_selectors": { "$ref": "promoted-products.json", "description": "Selectors to choose which products/offerings from the brand manifest product catalog to promote" + }, + "si_agent_url": { + "description": "MCP endpoint URL for the brand's SI agent. When present, hosts can connect users to conversational experiences about any of the offerings. The agent handles si_get_offering lookups and full conversations.", + "format": "uri", + "type": "string" } }, "required": [ diff --git a/schemas/cache/core/proposal.json b/schemas/cache/core/proposal.json new file mode 100644 index 00000000..619d54dc --- /dev/null +++ b/schemas/cache/core/proposal.json @@ -0,0 +1,72 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "A proposed media plan with budget allocations across products. Represents the publisher's strategic recommendation for how to structure a campaign based on the brief. Proposals are actionable - buyers can execute them directly via create_media_buy by providing the proposal_id.", + "properties": { + "allocations": { + "description": "Budget allocations across products. Allocation percentages MUST sum to 100. Publishers are responsible for ensuring the sum equals 100; buyers SHOULD validate this before execution.", + "items": { + "$ref": "product-allocation.json" + }, + "minItems": 1, + "type": "array" + }, + "brief_alignment": { + "description": "Explanation of how this proposal aligns with the campaign brief", + "type": "string" + }, + "description": { + "description": "Explanation of the proposal strategy and what it achieves", + "type": "string" + }, + "expires_at": { + "description": "When this proposal expires and can no longer be executed. After expiration, referenced products or pricing may no longer be available.", + "format": "date-time", + "type": "string" + }, + "ext": { + "$ref": "ext.json" + }, + "name": { + "description": "Human-readable name for this media plan proposal", + "type": "string" + }, + "proposal_id": { + "description": "Unique identifier for this proposal. Used to refine the proposal in subsequent get_products calls or to execute it via create_media_buy.", + "type": "string" + }, + "total_budget_guidance": { + "additionalProperties": true, + "description": "Optional budget guidance for this proposal", + "properties": { + "currency": { + "description": "ISO 4217 currency code", + "type": "string" + }, + "max": { + "description": "Maximum budget before diminishing returns", + "minimum": 0, + "type": "number" + }, + "min": { + "description": "Minimum recommended budget", + "minimum": 0, + "type": "number" + }, + "recommended": { + "description": "Recommended budget for optimal performance", + "minimum": 0, + "type": "number" + } + }, + "type": "object" + } + }, + "required": [ + "proposal_id", + "name", + "allocations" + ], + "title": "Proposal", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/core/reporting-webhook.json b/schemas/cache/core/reporting-webhook.json new file mode 100644 index 00000000..ff3f0736 --- /dev/null +++ b/schemas/cache/core/reporting-webhook.json @@ -0,0 +1,66 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Webhook configuration for automated reporting delivery. Configures where and how campaign performance reports are sent.", + "properties": { + "authentication": { + "additionalProperties": false, + "description": "Authentication configuration for webhook delivery (A2A-compatible)", + "properties": { + "credentials": { + "description": "Credentials for authentication. For Bearer: token sent in Authorization header. For HMAC-SHA256: shared secret used to generate signature. Minimum 32 characters. Exchanged out-of-band during onboarding.", + "minLength": 32, + "type": "string" + }, + "schemes": { + "description": "Array of authentication schemes. Supported: ['Bearer'] for simple token auth, ['HMAC-SHA256'] for signature verification (recommended for production)", + "items": { + "$ref": "../enums/auth-scheme.json" + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "schemes", + "credentials" + ], + "type": "object" + }, + "reporting_frequency": { + "description": "Frequency for automated reporting delivery. Must be supported by all products in the media buy.", + "enum": [ + "hourly", + "daily", + "monthly" + ], + "type": "string" + }, + "requested_metrics": { + "description": "Optional list of metrics to include in webhook notifications. If omitted, all available metrics are included. Must be subset of product's available_metrics.", + "items": { + "$ref": "../enums/available-metric.json" + }, + "type": "array", + "uniqueItems": true + }, + "token": { + "description": "Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.", + "minLength": 16, + "type": "string" + }, + "url": { + "description": "Webhook endpoint URL for reporting notifications", + "format": "uri", + "type": "string" + } + }, + "required": [ + "url", + "authentication", + "reporting_frequency" + ], + "title": "Reporting Webhook", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/core/targeting.json b/schemas/cache/core/targeting.json index 318ee547..9748d6ea 100644 --- a/schemas/cache/core/targeting.json +++ b/schemas/cache/core/targeting.json @@ -14,31 +14,70 @@ "frequency_cap": { "$ref": "frequency-cap.json" }, - "geo_country_any_of": { - "description": "Restrict delivery to specific countries (ISO codes). Use for regulatory compliance or RCT testing.", + "geo_countries": { + "description": "Restrict delivery to specific countries. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE').", "items": { "pattern": "^[A-Z]{2}$", "type": "string" }, "type": "array" }, - "geo_metro_any_of": { - "description": "Restrict delivery to specific metro areas (DMA codes). Use for regulatory compliance or RCT testing.", + "geo_metros": { + "description": "Restrict delivery to specific metro areas. Each entry specifies the classification system and target values. Seller must declare supported systems in get_adcp_capabilities.", "items": { - "type": "string" + "additionalProperties": false, + "properties": { + "system": { + "$ref": "../enums/metro-system.json", + "description": "Metro area classification system (e.g., 'nielsen_dma', 'uk_itl2')" + }, + "values": { + "description": "Metro codes within the system (e.g., ['501', '602'] for Nielsen DMAs)", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "system", + "values" + ], + "type": "object" }, "type": "array" }, - "geo_postal_code_any_of": { - "description": "Restrict delivery to specific postal/ZIP codes. Use for regulatory compliance or RCT testing.", + "geo_postal_areas": { + "description": "Restrict delivery to specific postal areas. Each entry specifies the postal system and target values. Seller must declare supported systems in get_adcp_capabilities.", "items": { - "type": "string" + "additionalProperties": false, + "properties": { + "system": { + "$ref": "../enums/postal-system.json", + "description": "Postal code system (e.g., 'us_zip', 'gb_outward'). System name encodes country and precision." + }, + "values": { + "description": "Postal codes within the system (e.g., ['10001', '10002'] for us_zip)", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "system", + "values" + ], + "type": "object" }, "type": "array" }, - "geo_region_any_of": { - "description": "Restrict delivery to specific regions/states. Use for regulatory compliance or RCT testing.", + "geo_regions": { + "description": "Restrict delivery to specific regions/states. ISO 3166-2 subdivision codes (e.g., 'US-CA', 'GB-SCT').", "items": { + "pattern": "^[A-Z]{2}-[A-Z0-9]{1,3}$", "type": "string" }, "type": "array" diff --git a/schemas/cache/creative/asset-types/index.json b/schemas/cache/creative/asset-types/index.json index 92edacd6..8515a9af 100644 --- a/schemas/cache/creative/asset-types/index.json +++ b/schemas/cache/creative/asset-types/index.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "adcp_version": "2.6.0", + "adcp_version": "latest", "architecture": { "format_aware_validation": { "description": "Creative manifests are validated in the context of their format specification", @@ -89,9 +89,9 @@ "typical_use": "DCO (Dynamic Creative Optimization), real-time personalization, server-side rendering" } }, - "baseUrl": "/schemas/2.6.0", + "baseUrl": "/schemas/latest", "description": "Registry of asset types used in AdCP creative manifests. Each asset type defines the structure of actual content payloads (what you send), not requirements or constraints (which belong in format specifications).", - "lastUpdated": "2026-01-13", + "lastUpdated": "2026-01-25", "title": "AdCP Asset Type Registry", "usage_notes": { "creative_manifests": "Creative manifests provide actual asset content, keyed by asset_id from the format. Asset type is determined by the format specification, not declared in the payload.", @@ -100,6 +100,6 @@ }, "version": "1.0.0", "versioning": { - "note": "AdCP uses build-time versioning. This directory contains schemas for AdCP 2.6.0. Full semantic versions are available at /schemas/{version}/ (e.g., /schemas/2.5.0/). Major version aliases point to the latest release: /schemas/v2/ \u2192 /schemas/2.6.0/." + "note": "AdCP uses build-time versioning. This directory contains schemas for AdCP latest. Full semantic versions are available at /schemas/{version}/ (e.g., /schemas/2.5.0/). Major version aliases point to the latest release: /schemas/vlatest/ \u2192 /schemas/latest/." } } \ No newline at end of file diff --git a/schemas/cache/enums/channels.json b/schemas/cache/enums/channels.json index 57f9ed12..c0faf843 100644 --- a/schemas/cache/enums/channels.json +++ b/schemas/cache/enums/channels.json @@ -1,17 +1,48 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Standard advertising channels supported by AdCP", + "description": "Standardized advertising media channels describing how buyers allocate budget. Channels are planning abstractions, not technical substrates. See the Media Channel Taxonomy specification for detailed definitions.", "enum": [ "display", - "video", - "audio", - "native", - "dooh", + "olv", + "social", + "search", "ctv", + "linear_tv", + "radio", + "streaming_audio", "podcast", - "retail", - "social" + "dooh", + "ooh", + "print", + "cinema", + "email", + "gaming", + "retail_media", + "influencer", + "affiliate", + "product_placement" ], - "title": "Advertising Channels", + "enumDescriptions": { + "affiliate": "Affiliate networks, comparison sites, and performance-based partnerships", + "cinema": "Movie theater advertising", + "ctv": "Connected TV and streaming on television screens", + "display": "Digital display advertising (banners, native, rich media) across web and app", + "dooh": "Digital out-of-home screens in public spaces", + "email": "Email advertising and sponsored newsletter content", + "gaming": "In-game advertising across platforms", + "influencer": "Creator and influencer marketing partnerships", + "linear_tv": "Traditional broadcast and cable television", + "olv": "Online video advertising outside CTV (pre-roll, outstream, in-app video)", + "ooh": "Classic out-of-home (physical billboards, transit, etc.)", + "podcast": "Podcast advertising (host-read or dynamically inserted)", + "print": "Newspapers, magazines, and other print publications", + "product_placement": "Product placement, branded content, and sponsorship integrations", + "radio": "Traditional AM/FM radio broadcast", + "retail_media": "Retail media networks and commerce marketplaces (Amazon, Walmart, Instacart)", + "search": "Search engine advertising and search networks", + "social": "Social media platforms (Facebook, Instagram, TikTok, LinkedIn, etc.)", + "streaming_audio": "Digital audio streaming services (Spotify, Pandora, etc.)" + }, + "title": "Media Channel", "type": "string" } \ No newline at end of file diff --git a/schemas/cache/enums/creative-status.json b/schemas/cache/enums/creative-status.json index 29ab67f1..17e7dcc6 100644 --- a/schemas/cache/enums/creative-status.json +++ b/schemas/cache/enums/creative-status.json @@ -5,10 +5,12 @@ "processing", "approved", "rejected", - "pending_review" + "pending_review", + "archived" ], "enumDescriptions": { "approved": "Creative has been approved and is ready for delivery", + "archived": "Creative has been archived and is excluded from default queries", "pending_review": "Creative is under review", "processing": "Creative is being processed or transcoded", "rejected": "Creative has been rejected due to policy or technical issues" diff --git a/schemas/cache/enums/geo-level.json b/schemas/cache/enums/geo-level.json new file mode 100644 index 00000000..95be4cb9 --- /dev/null +++ b/schemas/cache/enums/geo-level.json @@ -0,0 +1,12 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Geographic targeting granularity levels. Some levels (metro, postal_area) require a system specification.", + "enum": [ + "country", + "region", + "metro", + "postal_area" + ], + "title": "Geographic Targeting Level", + "type": "string" +} \ No newline at end of file diff --git a/schemas/cache/enums/metro-system.json b/schemas/cache/enums/metro-system.json new file mode 100644 index 00000000..a36595e1 --- /dev/null +++ b/schemas/cache/enums/metro-system.json @@ -0,0 +1,13 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Metro area classification systems for geographic targeting", + "enum": [ + "nielsen_dma", + "uk_itl1", + "uk_itl2", + "eurostat_nuts2", + "custom" + ], + "title": "Metro Area System", + "type": "string" +} \ No newline at end of file diff --git a/schemas/cache/enums/postal-system.json b/schemas/cache/enums/postal-system.json new file mode 100644 index 00000000..9a193a79 --- /dev/null +++ b/schemas/cache/enums/postal-system.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Postal code systems for geographic targeting. System names encode country and precision level.", + "enum": [ + "us_zip", + "us_zip_plus_four", + "gb_outward", + "gb_full", + "ca_fsa", + "ca_full", + "de_plz", + "fr_code_postal", + "au_postcode" + ], + "title": "Postal Code System", + "type": "string" +} \ No newline at end of file diff --git a/schemas/cache/enums/property-type.json b/schemas/cache/enums/property-type.json index ccc9fa65..79bc4e19 100644 --- a/schemas/cache/enums/property-type.json +++ b/schemas/cache/enums/property-type.json @@ -1,15 +1,26 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Types of advertising properties that can be represented in AdCP", + "description": "Types of addressable advertising properties with verifiable ownership. Property types are a subset of media channels - they represent inventory surfaces that can be validated via adagents.json.", "enum": [ "website", "mobile_app", "ctv_app", + "desktop_app", "dooh", "podcast", "radio", "streaming_audio" ], + "enumDescriptions": { + "ctv_app": "Connected TV applications, identified by platform-specific store IDs", + "desktop_app": "Desktop applications (Electron, native, Chromium wrappers), identified by application bundle IDs", + "dooh": "Digital out-of-home screen networks, identified by network/venue IDs", + "mobile_app": "Native mobile applications, identified by app store IDs or bundle identifiers", + "podcast": "Podcast feeds and episodes, identified by RSS feed URLs or podcast IDs", + "radio": "Radio station properties, identified by call signs or station IDs", + "streaming_audio": "Digital audio streaming properties, identified by platform-specific IDs", + "website": "Web properties accessible via browser, identified by domain" + }, "title": "Property Type", "type": "string" } \ No newline at end of file diff --git a/schemas/cache/enums/standard-format-ids.json b/schemas/cache/enums/standard-format-ids.json deleted file mode 100644 index 34e1670f..00000000 --- a/schemas/cache/enums/standard-format-ids.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "categories": { - "audio": [ - "audio_standard_15s", - "audio_standard_30s", - "audio_podcast_host_read", - "audio_programmatic" - ], - "display": [ - "display_300x250", - "display_728x90", - "display_320x50", - "display_160x600", - "display_970x250", - "display_336x280", - "display_expandable_300x250", - "display_expandable_728x90", - "display_interstitial_320x480", - "display_interstitial_desktop", - "display_dynamic_300x250", - "display_responsive" - ], - "dooh": [ - "dooh_landscape_static", - "dooh_portrait_video" - ], - "native": [ - "native_in_feed", - "native_content_recommendation", - "native_product" - ], - "universal": [ - "universal_carousel", - "universal_canvas", - "universal_takeover", - "universal_gallery", - "universal_reveal" - ], - "video": [ - "video_skippable_15s", - "video_skippable_30s", - "video_non_skippable_15s", - "video_non_skippable_30s", - "video_outstream_autoplay", - "video_vertical_story", - "video_rewarded_30s", - "video_pause_ad", - "video_ctv_non_skippable_30s" - ] - }, - "description": "Enumeration of all standard creative format identifiers in AdCP", - "dynamic_creative_formats": [ - "display_dynamic_300x250" - ], - "enum": [ - "display_300x250", - "display_728x90", - "display_320x50", - "display_160x600", - "display_970x250", - "display_336x280", - "display_expandable_300x250", - "display_expandable_728x90", - "display_interstitial_320x480", - "display_interstitial_desktop", - "display_dynamic_300x250", - "display_responsive", - "native_in_feed", - "native_content_recommendation", - "native_product", - "video_skippable_15s", - "video_skippable_30s", - "video_non_skippable_15s", - "video_non_skippable_30s", - "video_outstream_autoplay", - "video_vertical_story", - "video_rewarded_30s", - "video_pause_ad", - "video_ctv_non_skippable_30s", - "audio_standard_15s", - "audio_standard_30s", - "audio_podcast_host_read", - "audio_programmatic", - "universal_carousel", - "universal_canvas", - "universal_takeover", - "universal_gallery", - "universal_reveal", - "dooh_landscape_static", - "dooh_portrait_video" - ], - "title": "Standard Format IDs", - "type": "string", - "universal_formats": [ - "universal_carousel", - "universal_canvas", - "universal_takeover", - "universal_gallery", - "universal_reveal" - ] -} \ No newline at end of file diff --git a/schemas/cache/extensions/index.json b/schemas/cache/extensions/index.json index 9db856bd..e4bc98e7 100644 --- a/schemas/cache/extensions/index.json +++ b/schemas/cache/extensions/index.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "_generated": true, - "_generatedAt": "2026-01-13T23:32:36.210Z", + "_generatedAt": "2026-01-25T18:43:29.083Z", "description": "Auto-generated registry of formal AdCP extensions. Extensions provide typed schemas for vendor-specific or domain-specific data within the ext field. Agents declare which extensions they support in their agent card.", "extensions": {}, "title": "AdCP Extension Registry" diff --git a/schemas/cache/media-buy/create-media-buy-request.json b/schemas/cache/media-buy/create-media-buy-request.json index 2d2686b0..b37f8ae3 100644 --- a/schemas/cache/media-buy/create-media-buy-request.json +++ b/schemas/cache/media-buy/create-media-buy-request.json @@ -1,42 +1,17 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, - "description": "Request parameters for creating a media buy", + "dependencies": { + "proposal_id": [ + "total_budget" + ] + }, + "description": "Request parameters for creating a media buy. Supports two modes: (1) Manual mode - provide packages array with explicit line item configurations, or (2) Proposal mode - provide proposal_id and total_budget to execute a proposal from get_products. One of packages or proposal_id must be provided.", "properties": { - "brand_manifest": { - "$ref": "../core/brand-manifest-ref.json", - "description": "Brand information manifest serving as the namespace and identity for this media buy. Provides brand context, assets, and product catalog. Can be provided inline or as a URL reference to a hosted manifest. Can be cached and reused across multiple requests." - }, - "buyer_ref": { - "description": "Buyer's reference identifier for this media buy", - "type": "string" - }, - "context": { - "$ref": "../core/context.json" - }, - "end_time": { - "description": "Campaign end date/time in ISO 8601 format", - "format": "date-time", - "type": "string" - }, - "ext": { - "$ref": "../core/ext.json" - }, - "packages": { - "description": "Array of package configurations", - "items": { - "$ref": "package-request.json" - }, - "type": "array" - }, - "po_number": { - "description": "Purchase order number for tracking", - "type": "string" - }, - "reporting_webhook": { - "$comment": "Fields url, token, and authentication mirror push-notification-config.json. Inlined here because allOf + additionalProperties:false doesn't work in JSON Schema (additionalProperties can't see $ref properties). See CLAUDE.md 'Avoiding allOf with additionalProperties'.", + "artifact_webhook": { + "$comment": "Webhook configuration for content artifact delivery - enables governance validation. Same authentication structure as reporting_webhook.", "additionalProperties": true, - "description": "Optional webhook configuration for automated reporting delivery. Combines push_notification_config structure with reporting-specific fields.", + "description": "Optional webhook configuration for content artifact delivery. Used by governance agents to validate content adjacency. Seller pushes artifacts to this endpoint; orchestrator forwards to governance agent for validation.", "properties": { "authentication": { "additionalProperties": false, @@ -63,33 +38,27 @@ ], "type": "object" }, - "reporting_frequency": { - "description": "Frequency for automated reporting delivery. Must be supported by all products in the media buy.", + "batch_frequency": { + "description": "For batched delivery, how often to push artifacts. Required when delivery_mode is 'batched'.", "enum": [ "hourly", - "daily", - "monthly" + "daily" ], "type": "string" }, - "requested_metrics": { - "description": "Optional list of metrics to include in webhook notifications. If omitted, all available metrics are included. Must be subset of product's available_metrics.", - "items": { - "enum": [ - "impressions", - "spend", - "clicks", - "ctr", - "video_completions", - "completion_rate", - "conversions", - "viewability", - "engagement_rate" - ], - "type": "string" - }, - "type": "array", - "uniqueItems": true + "delivery_mode": { + "description": "How artifacts are delivered. 'realtime' pushes artifacts as impressions occur. 'batched' aggregates artifacts and pushes periodically (see batch_frequency).", + "enum": [ + "realtime", + "batched" + ], + "type": "string" + }, + "sampling_rate": { + "description": "Fraction of impressions to include (0-1). 1.0 = all impressions, 0.1 = 10% sample. Default: 1.0", + "maximum": 1, + "minimum": 0, + "type": "number" }, "token": { "description": "Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.", @@ -97,7 +66,7 @@ "type": "string" }, "url": { - "description": "Webhook endpoint URL for reporting notifications", + "description": "Webhook endpoint URL for artifact delivery", "format": "uri", "type": "string" } @@ -105,17 +74,74 @@ "required": [ "url", "authentication", - "reporting_frequency" + "delivery_mode" ], "type": "object" }, + "brand_manifest": { + "$ref": "../core/brand-manifest-ref.json", + "description": "Brand information manifest serving as the namespace and identity for this media buy. Provides brand context, assets, and product catalog. Can be provided inline or as a URL reference to a hosted manifest. Can be cached and reused across multiple requests." + }, + "buyer_ref": { + "description": "Buyer's reference identifier for this media buy", + "type": "string" + }, + "context": { + "$ref": "../core/context.json" + }, + "end_time": { + "description": "Campaign end date/time in ISO 8601 format", + "format": "date-time", + "type": "string" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "packages": { + "description": "Array of package configurations. Required when not using proposal_id. When executing a proposal, this can be omitted and packages will be derived from the proposal's allocations.", + "items": { + "$ref": "package-request.json" + }, + "type": "array" + }, + "po_number": { + "description": "Purchase order number for tracking", + "type": "string" + }, + "proposal_id": { + "description": "ID of a proposal from get_products to execute. When provided with total_budget, the publisher converts the proposal's allocation percentages into packages automatically. Alternative to providing packages array.", + "type": "string" + }, + "reporting_webhook": { + "$ref": "../core/reporting-webhook.json", + "description": "Optional webhook configuration for automated reporting delivery" + }, "start_time": { "$ref": "../core/start-timing.json" + }, + "total_budget": { + "additionalProperties": false, + "description": "Total budget for the media buy when executing a proposal. The publisher applies the proposal's allocation percentages to this amount to derive package budgets.", + "properties": { + "amount": { + "description": "Total budget amount", + "minimum": 0, + "type": "number" + }, + "currency": { + "description": "ISO 4217 currency code", + "type": "string" + } + }, + "required": [ + "amount", + "currency" + ], + "type": "object" } }, "required": [ "buyer_ref", - "packages", "brand_manifest", "start_time", "end_time" diff --git a/schemas/cache/media-buy/get-products-request.json b/schemas/cache/media-buy/get-products-request.json index dd50040d..177a73ac 100644 --- a/schemas/cache/media-buy/get-products-request.json +++ b/schemas/cache/media-buy/get-products-request.json @@ -8,7 +8,7 @@ "description": "Brand information manifest providing brand context, assets, and product catalog. Can be provided inline or as a URL reference to a hosted manifest." }, "brief": { - "description": "Natural language description of campaign requirements", + "description": "Natural language description of campaign requirements. When refining a proposal, can include instructions like 'focus more on German speakers' or 'increase mobile allocation'.", "type": "string" }, "context": { @@ -23,6 +23,10 @@ "property_list": { "$ref": "../core/property-list-ref.json", "description": "[AdCP 3.0] Reference to an externally managed property list. When provided, the sales agent should filter products to only those available on properties in the list." + }, + "proposal_id": { + "description": "Optional proposal ID to refine. When provided with a brief, the publisher will use the brief as refinement instructions for the specified proposal and return an updated version.", + "type": "string" } }, "required": [], diff --git a/schemas/cache/media-buy/get-products-response.json b/schemas/cache/media-buy/get-products-response.json index b0cbc817..31ca355a 100644 --- a/schemas/cache/media-buy/get-products-response.json +++ b/schemas/cache/media-buy/get-products-response.json @@ -26,6 +26,13 @@ "property_list_applied": { "description": "[AdCP 3.0] Indicates whether property_list filtering was applied. True if the agent filtered products based on the provided property_list. Absent or false if property_list was not provided or not supported by this agent.", "type": "boolean" + }, + "proposals": { + "description": "Optional array of proposed media plans with budget allocations across products. Publishers include proposals when they can provide strategic guidance based on the brief. Proposals are actionable - buyers can refine them via subsequent get_products calls or execute them directly via create_media_buy.", + "items": { + "$ref": "../core/proposal.json" + }, + "type": "array" } }, "required": [ diff --git a/schemas/cache/media-buy/list-creatives-response.json b/schemas/cache/media-buy/list-creatives-response.json index 96b857bb..64293e23 100644 --- a/schemas/cache/media-buy/list-creatives-response.json +++ b/schemas/cache/media-buy/list-creatives-response.json @@ -69,9 +69,8 @@ "assigned_packages": [ { "assigned_date": "2024-01-16T09:00:00Z", - "package_id": "pkg_ctv_001", - "package_name": "CTV Prime Time", - "status": "active" + "buyer_ref": "ctv_prime_time_q1", + "package_id": "pkg_ctv_001" } ], "assignment_count": 2 @@ -173,28 +172,18 @@ "format": "date-time", "type": "string" }, - "package_id": { - "description": "Package identifier", + "buyer_ref": { + "description": "Buyer's reference identifier for this package", "type": "string" }, - "package_name": { - "description": "Human-readable package name", - "type": "string" - }, - "status": { - "description": "Status of this specific assignment", - "enum": [ - "active", - "paused", - "ended" - ], + "package_id": { + "description": "Package identifier", "type": "string" } }, "required": [ "package_id", - "assigned_date", - "status" + "assigned_date" ], "type": "object" }, @@ -417,6 +406,11 @@ "minimum": 0, "type": "integer" }, + "processing": { + "description": "Number of creatives being processed", + "minimum": 0, + "type": "integer" + }, "rejected": { "description": "Number of rejected creatives", "minimum": 0, diff --git a/schemas/cache/media-buy/package-request.json b/schemas/cache/media-buy/package-request.json index f56c2295..81b1da94 100644 --- a/schemas/cache/media-buy/package-request.json +++ b/schemas/cache/media-buy/package-request.json @@ -17,15 +17,15 @@ "description": "Buyer's reference identifier for this package", "type": "string" }, - "creative_ids": { - "description": "Creative IDs to assign to this package at creation time (references existing library creatives)", + "creative_assignments": { + "description": "Assign existing library creatives to this package with optional weights and placement targeting", "items": { - "type": "string" + "$ref": "../core/creative-assignment.json" }, "type": "array" }, "creatives": { - "description": "Full creative objects to upload and assign to this package at creation time (alternative to creative_ids - creatives will be added to library). Supports both static and generative creatives.", + "description": "Upload new creative assets and assign to this package (creatives will be added to library). Use creative_assignments instead for existing library creatives.", "items": { "$ref": "../core/creative-asset.json" }, diff --git a/schemas/cache/media-buy/package-update.json b/schemas/cache/media-buy/package-update.json new file mode 100644 index 00000000..53124d5f --- /dev/null +++ b/schemas/cache/media-buy/package-update.json @@ -0,0 +1,72 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Package update configuration for update_media_buy. Identifies package by package_id or buyer_ref and specifies fields to modify. Fields not present are left unchanged. Note: product_id, format_ids, and pricing_option_id cannot be changed after creation.", + "oneOf": [ + { + "required": [ + "package_id" + ] + }, + { + "required": [ + "buyer_ref" + ] + } + ], + "properties": { + "bid_price": { + "description": "Updated bid price for auction-based pricing options (only applies when pricing_option is auction-based)", + "minimum": 0, + "type": "number" + }, + "budget": { + "description": "Updated budget allocation for this package in the currency specified by the pricing option", + "minimum": 0, + "type": "number" + }, + "buyer_ref": { + "description": "Buyer's reference for the package to update", + "type": "string" + }, + "creative_assignments": { + "description": "Replace creative assignments for this package with optional weights and placement targeting. Uses replacement semantics - omit to leave assignments unchanged.", + "items": { + "$ref": "../core/creative-assignment.json" + }, + "type": "array" + }, + "creatives": { + "description": "Upload new creative assets and assign to this package (creatives will be added to library). Use creative_assignments instead for existing library creatives.", + "items": { + "$ref": "../core/creative-asset.json" + }, + "maxItems": 100, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "impressions": { + "description": "Updated impression goal for this package", + "minimum": 0, + "type": "number" + }, + "pacing": { + "$ref": "../enums/pacing.json" + }, + "package_id": { + "description": "Publisher's ID of package to update", + "type": "string" + }, + "paused": { + "description": "Pause/resume specific package (true = paused, false = active)", + "type": "boolean" + }, + "targeting_overlay": { + "$ref": "../core/targeting.json" + } + }, + "title": "Package Update", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/media-buy/update-media-buy-request.json b/schemas/cache/media-buy/update-media-buy-request.json index f8af4146..f71066bd 100644 --- a/schemas/cache/media-buy/update-media-buy-request.json +++ b/schemas/cache/media-buy/update-media-buy-request.json @@ -37,77 +37,7 @@ "packages": { "description": "Package-specific updates", "items": { - "additionalProperties": true, - "oneOf": [ - { - "required": [ - "package_id" - ] - }, - { - "required": [ - "buyer_ref" - ] - } - ], - "properties": { - "bid_price": { - "description": "Updated bid price for auction-based pricing options (only applies when pricing_option is auction-based)", - "minimum": 0, - "type": "number" - }, - "budget": { - "description": "Updated budget allocation for this package in the currency specified by the pricing option", - "minimum": 0, - "type": "number" - }, - "buyer_ref": { - "description": "Buyer's reference for the package to update", - "type": "string" - }, - "creative_assignments": { - "description": "Full creative assignment objects with weights and placement targeting (alternative to creative_ids - provides granular control over weights and placement targeting). Uses replacement semantics like creative_ids.", - "items": { - "$ref": "../core/creative-assignment.json" - }, - "type": "array" - }, - "creative_ids": { - "description": "Update creative assignments (references existing library creatives)", - "items": { - "type": "string" - }, - "type": "array" - }, - "creatives": { - "description": "Full creative objects to upload and assign to this package (alternative to creative_ids - creatives will be added to library). Supports both static and generative creatives.", - "items": { - "$ref": "../core/creative-asset.json" - }, - "maxItems": 100, - "type": "array" - }, - "impressions": { - "description": "Updated impression goal for this package", - "minimum": 0, - "type": "number" - }, - "pacing": { - "$ref": "../enums/pacing.json" - }, - "package_id": { - "description": "Publisher's ID of package to update", - "type": "string" - }, - "paused": { - "description": "Pause/resume specific package (true = paused, false = active)", - "type": "boolean" - }, - "targeting_overlay": { - "$ref": "../core/targeting.json" - } - }, - "type": "object" + "$ref": "package-update.json" }, "type": "array" }, @@ -117,7 +47,11 @@ }, "push_notification_config": { "$ref": "../core/push-notification-config.json", - "description": "Optional webhook configuration for async update notifications. Publisher will send webhook when update completes if operation takes longer than immediate response time." + "description": "Optional webhook configuration for async update notifications. Publisher will send webhook when update completes if operation takes longer than immediate response time. This is separate from reporting_webhook which configures ongoing campaign reporting." + }, + "reporting_webhook": { + "$ref": "../core/reporting-webhook.json", + "description": "Optional webhook configuration for automated reporting delivery. Updates the reporting configuration for this media buy." }, "start_time": { "$ref": "../core/start-timing.json" diff --git a/schemas/cache/property/list-property-features-request.json b/schemas/cache/property/list-property-features-request.json deleted file mode 100644 index 4dcf8c47..00000000 --- a/schemas/cache/property/list-property-features-request.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "description": "Request payload for list_property_features task. Discovers what features a governance agent can evaluate.", - "properties": { - "countries": { - "description": "Filter to features available in these countries", - "items": { - "type": "string" - }, - "type": "array" - }, - "ext": { - "$ref": "../core/ext.json" - }, - "property_types": { - "description": "Filter to features available for these property types", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "title": "List Property Features Request", - "type": "object" -} \ No newline at end of file diff --git a/schemas/cache/property/list-property-features-response.json b/schemas/cache/property/list-property-features-response.json deleted file mode 100644 index 17717e14..00000000 --- a/schemas/cache/property/list-property-features-response.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "description": "Response payload for list_property_features task. Returns the features this governance agent can evaluate.", - "properties": { - "ext": { - "$ref": "../core/ext.json" - }, - "features": { - "description": "Features this agent can evaluate", - "items": { - "$ref": "property-feature-definition.json" - }, - "type": "array" - } - }, - "required": [ - "features" - ], - "title": "List Property Features Response", - "type": "object" -} \ No newline at end of file diff --git a/schemas/cache/protocol/get-adcp-capabilities-request.json b/schemas/cache/protocol/get-adcp-capabilities-request.json new file mode 100644 index 00000000..d368494c --- /dev/null +++ b/schemas/cache/protocol/get-adcp-capabilities-request.json @@ -0,0 +1,27 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Request payload for get_adcp_capabilities task. Protocol-level capability discovery that works across all AdCP protocols.", + "properties": { + "context": { + "$ref": "../core/context.json" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "protocols": { + "description": "Specific protocols to query capabilities for. If omitted, returns capabilities for all supported protocols.", + "items": { + "enum": [ + "media_buy", + "signals", + "sponsored_intelligence" + ], + "type": "string" + }, + "type": "array" + } + }, + "title": "Get AdCP Capabilities Request", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/protocol/get-adcp-capabilities-response.json b/schemas/cache/protocol/get-adcp-capabilities-response.json new file mode 100644 index 00000000..90368f32 --- /dev/null +++ b/schemas/cache/protocol/get-adcp-capabilities-response.json @@ -0,0 +1,390 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Response payload for get_adcp_capabilities task. Protocol-level capability discovery across all AdCP protocols. Each domain protocol has its own capability section.", + "properties": { + "adcp": { + "description": "Core AdCP protocol information", + "properties": { + "major_versions": { + "description": "AdCP major versions supported by this seller. Major versions indicate breaking changes.", + "items": { + "minimum": 1, + "type": "integer" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "major_versions" + ], + "type": "object" + }, + "context": { + "$ref": "../core/context.json" + }, + "errors": { + "description": "Task-specific errors and warnings", + "items": { + "$ref": "../core/error.json" + }, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "extensions_supported": { + "description": "Extension namespaces this agent supports. Buyers can expect meaningful data in ext.{namespace} fields on responses from this agent. Extension schemas are published in the AdCP extension registry.", + "items": { + "description": "Extension namespace (lowercase alphanumeric with underscores, e.g., 'scope3', 'garm', 'iab_tcf')", + "pattern": "^[a-z][a-z0-9_]*$", + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "governance": { + "description": "Governance protocol capabilities. Only present if governance is in supported_protocols. Governance agents provide property data like compliance scores, brand safety ratings, and sustainability metrics.", + "properties": { + "property_features": { + "description": "Property features this governance agent can evaluate. Each feature describes a score, rating, or certification the agent can provide for properties.", + "items": { + "properties": { + "categories": { + "description": "For categorical features, the valid values", + "items": { + "type": "string" + }, + "type": "array" + }, + "description": { + "description": "Human-readable description of what this feature measures", + "type": "string" + }, + "feature_id": { + "description": "Unique identifier for this feature (e.g., 'consent_quality', 'coppa_certified', 'carbon_score')", + "type": "string" + }, + "methodology_url": { + "description": "URL to documentation explaining how this feature is calculated or measured. Helps buyers understand and compare methodologies across vendors.", + "format": "uri", + "type": "string" + }, + "range": { + "description": "For quantitative features, the valid range", + "properties": { + "max": { + "description": "Maximum value", + "type": "number" + }, + "min": { + "description": "Minimum value", + "type": "number" + } + }, + "required": [ + "min", + "max" + ], + "type": "object" + }, + "type": { + "description": "Data type: 'binary' for yes/no, 'quantitative' for numeric scores, 'categorical' for enum values", + "enum": [ + "binary", + "quantitative", + "categorical" + ], + "type": "string" + } + }, + "required": [ + "feature_id", + "type" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "last_updated": { + "description": "ISO 8601 timestamp of when capabilities were last updated. Buyers can use this for cache invalidation.", + "format": "date-time", + "type": "string" + }, + "media_buy": { + "description": "Media-buy protocol capabilities. Only present if media_buy is in supported_protocols.", + "properties": { + "execution": { + "description": "Technical execution capabilities for media buying", + "properties": { + "axe_integrations": { + "description": "Agentic ad exchange (AXE) integrations supported. URLs are canonical identifiers for exchanges this seller can execute through.", + "items": { + "format": "uri", + "type": "string" + }, + "type": "array" + }, + "creative_specs": { + "description": "Creative specification support", + "properties": { + "mraid_versions": { + "description": "MRAID versions supported for rich media mobile creatives", + "items": { + "pattern": "^[0-9]+\\.[0-9]+$", + "type": "string" + }, + "type": "array" + }, + "simid": { + "description": "SIMID support for interactive video ads", + "type": "boolean" + }, + "vast_versions": { + "description": "VAST versions supported for video creatives", + "items": { + "pattern": "^[0-9]+\\.[0-9]+$", + "type": "string" + }, + "type": "array" + }, + "vpaid": { + "description": "VPAID support for interactive video ads", + "type": "boolean" + } + }, + "type": "object" + }, + "targeting": { + "description": "Targeting capabilities. If declared true/supported, buyer can use these targeting parameters and seller MUST honor them.", + "properties": { + "geo_countries": { + "description": "Supports country-level geo targeting using ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE')", + "type": "boolean" + }, + "geo_metros": { + "description": "Metro area targeting support. Specifies which classification systems are supported.", + "properties": { + "eurostat_nuts2": { + "description": "Supports Eurostat NUTS Level 2 regions (EU)", + "type": "boolean" + }, + "nielsen_dma": { + "description": "Supports Nielsen DMA codes (US market, e.g., '501' for NYC)", + "type": "boolean" + }, + "uk_itl1": { + "description": "Supports UK ITL Level 1 regions", + "type": "boolean" + }, + "uk_itl2": { + "description": "Supports UK ITL Level 2 regions", + "type": "boolean" + } + }, + "type": "object" + }, + "geo_postal_areas": { + "description": "Postal area targeting support. Specifies which postal code systems are supported. System names encode country and precision.", + "properties": { + "au_postcode": { + "description": "Australian postcode, 4 digits (e.g., '2000')", + "type": "boolean" + }, + "ca_fsa": { + "description": "Canadian Forward Sortation Area (e.g., 'K1A')", + "type": "boolean" + }, + "ca_full": { + "description": "Canadian full postal code (e.g., 'K1A 0B1')", + "type": "boolean" + }, + "de_plz": { + "description": "German Postleitzahl, 5 digits (e.g., '10115')", + "type": "boolean" + }, + "fr_code_postal": { + "description": "French code postal, 5 digits (e.g., '75001')", + "type": "boolean" + }, + "gb_full": { + "description": "UK full postcode (e.g., 'SW1A 1AA')", + "type": "boolean" + }, + "gb_outward": { + "description": "UK postcode district / outward code (e.g., 'SW1', 'EC1')", + "type": "boolean" + }, + "us_zip": { + "description": "US 5-digit ZIP codes (e.g., '10001')", + "type": "boolean" + }, + "us_zip_plus_four": { + "description": "US 9-digit ZIP+4 codes (e.g., '10001-1234')", + "type": "boolean" + } + }, + "type": "object" + }, + "geo_regions": { + "description": "Supports region/state-level geo targeting using ISO 3166-2 subdivision codes (e.g., 'US-NY', 'GB-SCT', 'DE-BY')", + "type": "boolean" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "features": { + "$ref": "../core/media-buy-features.json" + }, + "portfolio": { + "description": "Information about the seller's media inventory portfolio", + "properties": { + "advertising_policies": { + "description": "Advertising content policies, restrictions, and guidelines", + "maxLength": 10000, + "type": "string" + }, + "description": { + "description": "Markdown-formatted description of the inventory portfolio", + "maxLength": 5000, + "type": "string" + }, + "primary_channels": { + "description": "Primary advertising channels in this portfolio", + "items": { + "$ref": "../enums/channels.json" + }, + "type": "array" + }, + "primary_countries": { + "description": "Primary countries (ISO 3166-1 alpha-2) where inventory is concentrated", + "items": { + "pattern": "^[A-Z]{2}$", + "type": "string" + }, + "type": "array" + }, + "publisher_domains": { + "description": "Publisher domains this seller is authorized to represent. Buyers should fetch each publisher's adagents.json for property definitions.", + "items": { + "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$", + "type": "string" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "publisher_domains" + ], + "type": "object" + } + }, + "type": "object" + }, + "signals": { + "description": "Signals protocol capabilities. Only present if signals is in supported_protocols. Reserved for future use.", + "properties": { + "features": { + "additionalProperties": { + "type": "boolean" + }, + "description": "Optional signals features supported", + "type": "object" + } + }, + "type": "object" + }, + "sponsored_intelligence": { + "description": "Sponsored Intelligence protocol capabilities. Only present if sponsored_intelligence is in supported_protocols. SI agents handle conversational brand experiences.", + "properties": { + "brand_manifest_url": { + "description": "URL to brand manifest with colors, fonts, logos, tone", + "format": "uri", + "type": "string" + }, + "capabilities": { + "$ref": "../sponsored-intelligence/si-capabilities.json", + "description": "Modalities, components, and commerce capabilities" + }, + "endpoint": { + "description": "SI agent endpoint configuration", + "properties": { + "preferred": { + "description": "Preferred transport when host supports multiple", + "enum": [ + "mcp", + "a2a" + ], + "type": "string" + }, + "transports": { + "description": "Available protocol transports. Hosts select based on their capabilities.", + "items": { + "additionalProperties": true, + "properties": { + "type": { + "description": "Protocol transport type", + "enum": [ + "mcp", + "a2a" + ], + "type": "string" + }, + "url": { + "description": "Agent endpoint URL for this transport", + "format": "uri", + "type": "string" + } + }, + "required": [ + "type", + "url" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "transports" + ], + "type": "object" + } + }, + "required": [ + "endpoint", + "capabilities" + ], + "type": "object" + }, + "supported_protocols": { + "description": "Which AdCP domain protocols this seller supports", + "items": { + "enum": [ + "media_buy", + "signals", + "governance", + "sponsored_intelligence" + ], + "type": "string" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "adcp", + "supported_protocols" + ], + "title": "Get AdCP Capabilities Response", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/protocols/adcp-extension.json b/schemas/cache/protocols/adcp-extension.json index 47f1dabb..9f1fe4df 100644 --- a/schemas/cache/protocols/adcp-extension.json +++ b/schemas/cache/protocols/adcp-extension.json @@ -1,17 +1,20 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, - "description": "Parameters for declaring AdCP support in agent discovery. For A2A, use in extensions[].params. For MCP, use in _meta['adcontextprotocol.org'].", + "deprecated": true, + "deprecation_note": "AdCP discovery now uses native MCP/A2A tool discovery. If an agent has 'get_adcp_capabilities' tool, it supports AdCP. Call get_adcp_capabilities for version, protocols, features, and capabilities.", + "description": "DEPRECATED: Use tool-based discovery instead. Check for 'get_adcp_capabilities' tool in the agent's tool list, then call it for full capability details. This extension schema is maintained for backward compatibility only.", "properties": { "adcp_version": { - "description": "Semantic version of the AdCP specification this agent implements (e.g., '2.5.0'). Extension schemas are versioned along with the AdCP spec.", + "deprecated": true, + "description": "DEPRECATED: Use get_adcp_capabilities response adcp.major_versions instead.", "pattern": "^\\d+\\.\\d+\\.\\d+$", "type": "string" }, "extensions_supported": { - "description": "Typed extensions this agent supports. Each extension has a formal schema in /schemas/extensions/. Extension version is determined by adcp_version.", + "deprecated": true, + "description": "DEPRECATED: Typed extensions can be declared in get_adcp_capabilities ext field.", "items": { - "description": "Extension namespace (e.g., 'sustainability'). Must be lowercase alphanumeric with underscores.", "pattern": "^[a-z][a-z0-9_]*$", "type": "string" }, @@ -19,7 +22,8 @@ "uniqueItems": true }, "protocols_supported": { - "description": "AdCP protocol domains supported by this agent. At least one must be specified.", + "deprecated": true, + "description": "DEPRECATED: Use get_adcp_capabilities response supported_protocols instead.", "items": { "enum": [ "media_buy", @@ -37,6 +41,6 @@ "adcp_version", "protocols_supported" ], - "title": "AdCP Agent Card Extension Params", + "title": "AdCP Agent Card Extension Params (Deprecated)", "type": "object" } \ No newline at end of file diff --git a/schemas/cache/sponsored-intelligence/si-capabilities.json b/schemas/cache/sponsored-intelligence/si-capabilities.json new file mode 100644 index 00000000..301c287e --- /dev/null +++ b/schemas/cache/sponsored-intelligence/si-capabilities.json @@ -0,0 +1,128 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Capabilities that a brand agent declares or a host supports", + "properties": { + "commerce": { + "additionalProperties": true, + "description": "Commerce capabilities", + "properties": { + "acp_checkout": { + "description": "Supports ACP (Agentic Commerce Protocol) checkout handoff", + "type": "boolean" + } + }, + "type": "object" + }, + "components": { + "additionalProperties": true, + "description": "Visual components supported", + "properties": { + "extensions": { + "additionalProperties": true, + "description": "Platform-specific extensions (chatgpt_apps_sdk, maps, forms, etc.)", + "type": "object" + }, + "standard": { + "description": "Standard components that all SI hosts must render", + "items": { + "enum": [ + "text", + "link", + "image", + "product_card", + "carousel", + "action_button" + ], + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "modalities": { + "additionalProperties": true, + "description": "Interaction modalities supported", + "properties": { + "avatar": { + "description": "Animated video presence with brand avatar", + "oneOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": true, + "properties": { + "avatar_id": { + "description": "Brand avatar identifier", + "type": "string" + }, + "provider": { + "description": "Avatar provider (d-id, heygen, synthesia, etc.)", + "type": "string" + } + }, + "type": "object" + } + ] + }, + "conversational": { + "default": true, + "description": "Pure text exchange - the baseline modality", + "type": "boolean" + }, + "video": { + "description": "Brand video content playback", + "oneOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": true, + "properties": { + "formats": { + "description": "Supported video formats (mp4, webm, etc.)", + "items": { + "type": "string" + }, + "type": "array" + }, + "max_duration_seconds": { + "description": "Maximum video duration", + "type": "integer" + } + }, + "type": "object" + } + ] + }, + "voice": { + "description": "Audio-based interaction using brand voice", + "oneOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": true, + "properties": { + "provider": { + "description": "TTS provider (elevenlabs, openai, etc.)", + "type": "string" + }, + "voice_id": { + "description": "Brand voice identifier", + "type": "string" + } + }, + "type": "object" + } + ] + } + }, + "type": "object" + } + }, + "title": "SI Capabilities", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/sponsored-intelligence/si-get-offering-request.json b/schemas/cache/sponsored-intelligence/si-get-offering-request.json new file mode 100644 index 00000000..1a99ae85 --- /dev/null +++ b/schemas/cache/sponsored-intelligence/si-get-offering-request.json @@ -0,0 +1,35 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Get offering details and availability before session handoff. Returns offering information, availability status, and optionally matching products based on context.", + "properties": { + "context": { + "description": "Optional natural language context about user intent for personalized results (e.g., 'mens size 14 near Cincinnati'). Must be anonymous - no PII.", + "type": "string" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "include_products": { + "default": false, + "description": "Whether to include matching products in the response", + "type": "boolean" + }, + "offering_id": { + "description": "Offering identifier from promoted offerings to get details for", + "type": "string" + }, + "product_limit": { + "default": 5, + "description": "Maximum number of matching products to return", + "maximum": 50, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "offering_id" + ], + "title": "SI Get Offering Request", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/sponsored-intelligence/si-get-offering-response.json b/schemas/cache/sponsored-intelligence/si-get-offering-response.json new file mode 100644 index 00000000..6b6fa4ff --- /dev/null +++ b/schemas/cache/sponsored-intelligence/si-get-offering-response.json @@ -0,0 +1,142 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Offering details, availability status, and optionally matching products. Use the offering_token in si_initiate_session for correlation.", + "properties": { + "alternative_offering_ids": { + "description": "Alternative offerings to consider if this one is unavailable", + "items": { + "type": "string" + }, + "type": "array" + }, + "available": { + "description": "Whether the offering is currently available", + "type": "boolean" + }, + "checked_at": { + "description": "When this offering information was retrieved", + "format": "date-time", + "type": "string" + }, + "errors": { + "description": "Errors during offering lookup", + "items": { + "$ref": "../core/error.json" + }, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "matching_products": { + "description": "Products matching the request context. Only included if include_products was true.", + "items": { + "additionalProperties": true, + "properties": { + "availability_summary": { + "description": "Brief availability info (e.g., 'In stock', 'Size 14 available', '3 left')", + "type": "string" + }, + "image_url": { + "description": "Product image", + "format": "uri", + "type": "string" + }, + "name": { + "description": "Product name", + "type": "string" + }, + "original_price": { + "description": "Original price if on sale", + "type": "string" + }, + "price": { + "description": "Display price (e.g., '$129', '$89.99')", + "type": "string" + }, + "product_id": { + "description": "Product identifier", + "type": "string" + }, + "url": { + "description": "Product detail page URL", + "format": "uri", + "type": "string" + } + }, + "required": [ + "product_id", + "name" + ], + "type": "object" + }, + "type": "array" + }, + "offering": { + "additionalProperties": true, + "description": "Offering details", + "properties": { + "expires_at": { + "description": "When this offering expires", + "format": "date-time", + "type": "string" + }, + "image_url": { + "description": "Hero image for the offering", + "format": "uri", + "type": "string" + }, + "landing_url": { + "description": "Landing page URL", + "format": "uri", + "type": "string" + }, + "offering_id": { + "description": "Offering identifier", + "type": "string" + }, + "price_hint": { + "description": "Price indication (e.g., 'from $199', '50% off')", + "type": "string" + }, + "summary": { + "description": "Brief summary of the offering", + "type": "string" + }, + "tagline": { + "description": "Short promotional tagline", + "type": "string" + }, + "title": { + "description": "Offering title", + "type": "string" + } + }, + "type": "object" + }, + "offering_token": { + "description": "Token to pass to si_initiate_session for session continuity. Brand stores the full query context server-side (products shown, order, context) so they can resolve references like 'the second one' when the session starts.", + "type": "string" + }, + "total_matching": { + "description": "Total number of products matching the context (may be more than returned in matching_products)", + "minimum": 0, + "type": "integer" + }, + "ttl_seconds": { + "description": "How long this offering information is valid (seconds). Host should re-fetch after TTL expires.", + "minimum": 0, + "type": "integer" + }, + "unavailable_reason": { + "description": "If not available, why (e.g., 'expired', 'sold_out', 'region_restricted')", + "type": "string" + } + }, + "required": [ + "available" + ], + "title": "SI Get Offering Response", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/sponsored-intelligence/si-identity.json b/schemas/cache/sponsored-intelligence/si-identity.json new file mode 100644 index 00000000..fdd55bd9 --- /dev/null +++ b/schemas/cache/sponsored-intelligence/si-identity.json @@ -0,0 +1,101 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "User identity shared with brand agent (with explicit consent)", + "properties": { + "anonymous_session_id": { + "description": "Session ID for anonymous users (when consent_granted is false)", + "type": "string" + }, + "consent_granted": { + "description": "Whether user consented to share identity", + "type": "boolean" + }, + "consent_scope": { + "description": "What data was consented to share", + "items": { + "enum": [ + "name", + "email", + "shipping_address", + "phone", + "locale" + ], + "type": "string" + }, + "type": "array" + }, + "consent_timestamp": { + "description": "When consent was granted (ISO 8601)", + "format": "date-time", + "type": "string" + }, + "privacy_policy_acknowledged": { + "additionalProperties": true, + "description": "Brand privacy policy acknowledgment", + "properties": { + "brand_policy_url": { + "description": "URL to brand's privacy policy", + "format": "uri", + "type": "string" + }, + "brand_policy_version": { + "description": "Version of policy acknowledged", + "type": "string" + } + }, + "type": "object" + }, + "user": { + "additionalProperties": true, + "description": "User data (only present if consent_granted is true)", + "properties": { + "email": { + "description": "User's email address", + "format": "email", + "type": "string" + }, + "locale": { + "description": "User's locale (e.g., en-US)", + "type": "string" + }, + "name": { + "description": "User's display name", + "type": "string" + }, + "phone": { + "description": "User's phone number", + "type": "string" + }, + "shipping_address": { + "additionalProperties": true, + "description": "User's shipping address for accurate pricing", + "properties": { + "city": { + "type": "string" + }, + "country": { + "type": "string" + }, + "postal_code": { + "type": "string" + }, + "state": { + "type": "string" + }, + "street": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "consent_granted" + ], + "title": "SI Identity", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/sponsored-intelligence/si-initiate-session-request.json b/schemas/cache/sponsored-intelligence/si-initiate-session-request.json new file mode 100644 index 00000000..56e40d27 --- /dev/null +++ b/schemas/cache/sponsored-intelligence/si-initiate-session-request.json @@ -0,0 +1,43 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Host initiates a session with a brand agent", + "properties": { + "context": { + "description": "Conversation handoff from the host describing what the user needs", + "type": "string" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "identity": { + "$ref": "si-identity.json" + }, + "media_buy_id": { + "description": "AdCP media buy ID if session was triggered by advertising", + "type": "string" + }, + "offering_id": { + "description": "Brand-specific offering identifier to apply", + "type": "string" + }, + "offering_token": { + "description": "Token from si_get_offering response for session continuity. Brand uses this to recall what products were shown to the user, enabling natural references like 'the second one' or 'that blue shoe'.", + "type": "string" + }, + "placement": { + "description": "Where this session was triggered (e.g., 'chatgpt_search', 'claude_chat')", + "type": "string" + }, + "supported_capabilities": { + "$ref": "si-capabilities.json", + "description": "What capabilities the host supports" + } + }, + "required": [ + "context", + "identity" + ], + "title": "SI Initiate Session Request", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/sponsored-intelligence/si-initiate-session-response.json b/schemas/cache/sponsored-intelligence/si-initiate-session-response.json new file mode 100644 index 00000000..7667d96d --- /dev/null +++ b/schemas/cache/sponsored-intelligence/si-initiate-session-response.json @@ -0,0 +1,48 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Brand agent's response to session initiation", + "properties": { + "errors": { + "description": "Errors during session initiation", + "items": { + "$ref": "../core/error.json" + }, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "negotiated_capabilities": { + "$ref": "si-capabilities.json", + "description": "Intersection of brand and host capabilities for this session" + }, + "response": { + "additionalProperties": true, + "description": "Brand agent's initial response", + "properties": { + "message": { + "description": "Conversational message from brand agent", + "type": "string" + }, + "ui_elements": { + "description": "Visual components to render", + "items": { + "$ref": "si-ui-element.json" + }, + "type": "array" + } + }, + "type": "object" + }, + "session_id": { + "description": "Unique session identifier for subsequent messages", + "type": "string" + } + }, + "required": [ + "session_id" + ], + "title": "SI Initiate Session Response", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/sponsored-intelligence/si-send-message-request.json b/schemas/cache/sponsored-intelligence/si-send-message-request.json new file mode 100644 index 00000000..29a65602 --- /dev/null +++ b/schemas/cache/sponsored-intelligence/si-send-message-request.json @@ -0,0 +1,50 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "anyOf": [ + { + "required": [ + "message" + ] + }, + { + "required": [ + "action_response" + ] + } + ], + "description": "Send a message to the brand agent within an active session", + "properties": { + "action_response": { + "additionalProperties": true, + "description": "Response to a previous action_button (e.g., user clicked checkout)", + "properties": { + "action": { + "description": "The action that was triggered", + "type": "string" + }, + "payload": { + "description": "Action-specific response data", + "type": "object" + } + }, + "type": "object" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "message": { + "description": "User's message to the brand agent", + "type": "string" + }, + "session_id": { + "description": "Active session identifier", + "type": "string" + } + }, + "required": [ + "session_id" + ], + "title": "SI Send Message Request", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/sponsored-intelligence/si-send-message-response.json b/schemas/cache/sponsored-intelligence/si-send-message-response.json new file mode 100644 index 00000000..57ec1950 --- /dev/null +++ b/schemas/cache/sponsored-intelligence/si-send-message-response.json @@ -0,0 +1,113 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Brand agent's response to a user message", + "properties": { + "errors": { + "items": { + "$ref": "../core/error.json" + }, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "handoff": { + "additionalProperties": true, + "description": "Handoff request when session_status is pending_handoff", + "properties": { + "context_for_checkout": { + "additionalProperties": true, + "description": "Context to pass to ACP for seamless checkout", + "properties": { + "applied_offers": { + "description": "Offer IDs that were applied during the conversation", + "items": { + "type": "string" + }, + "type": "array" + }, + "conversation_summary": { + "description": "Summary of the conversation leading to purchase", + "type": "string" + } + }, + "type": "object" + }, + "intent": { + "additionalProperties": true, + "description": "For transaction handoffs: what the user wants to purchase", + "properties": { + "action": { + "description": "The commerce action (e.g., 'purchase')", + "type": "string" + }, + "price": { + "description": "Price information", + "properties": { + "amount": { + "type": "number" + }, + "currency": { + "type": "string" + } + }, + "type": "object" + }, + "product": { + "description": "Product details for checkout", + "type": "object" + } + }, + "type": "object" + }, + "type": { + "description": "Type of handoff: transaction (ready for ACP checkout) or complete (conversation done)", + "enum": [ + "transaction", + "complete" + ], + "type": "string" + } + }, + "type": "object" + }, + "response": { + "additionalProperties": true, + "description": "Brand agent's response", + "properties": { + "message": { + "description": "Conversational message from brand agent", + "type": "string" + }, + "ui_elements": { + "description": "Visual components to render", + "items": { + "$ref": "si-ui-element.json" + }, + "type": "array" + } + }, + "type": "object" + }, + "session_id": { + "description": "Session identifier", + "type": "string" + }, + "session_status": { + "description": "Current session status", + "enum": [ + "active", + "pending_handoff", + "complete" + ], + "type": "string" + } + }, + "required": [ + "session_id", + "session_status" + ], + "title": "SI Send Message Response", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/sponsored-intelligence/si-terminate-session-request.json b/schemas/cache/sponsored-intelligence/si-terminate-session-request.json new file mode 100644 index 00000000..c4ac90d2 --- /dev/null +++ b/schemas/cache/sponsored-intelligence/si-terminate-session-request.json @@ -0,0 +1,64 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Request to terminate an SI session", + "properties": { + "ext": { + "$ref": "../core/ext.json" + }, + "reason": { + "description": "Reason for termination", + "enum": [ + "handoff_transaction", + "handoff_complete", + "user_exit", + "session_timeout", + "host_terminated" + ], + "type": "string" + }, + "session_id": { + "description": "Session identifier to terminate", + "type": "string" + }, + "termination_context": { + "additionalProperties": true, + "description": "Context for the termination", + "properties": { + "cause": { + "description": "For host_terminated - why host ended session", + "type": "string" + }, + "summary": { + "description": "Summary of the conversation", + "type": "string" + }, + "transaction_intent": { + "additionalProperties": true, + "description": "For handoff_transaction - what user wants to buy", + "properties": { + "action": { + "enum": [ + "purchase", + "subscribe" + ], + "type": "string" + }, + "product": { + "description": "Product/service details", + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "session_id", + "reason" + ], + "title": "SI Terminate Session Request", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/sponsored-intelligence/si-terminate-session-response.json b/schemas/cache/sponsored-intelligence/si-terminate-session-response.json new file mode 100644 index 00000000..63425498 --- /dev/null +++ b/schemas/cache/sponsored-intelligence/si-terminate-session-response.json @@ -0,0 +1,70 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "description": "Confirmation of session termination", + "properties": { + "acp_handoff": { + "additionalProperties": true, + "description": "ACP checkout handoff data (for handoff_transaction)", + "properties": { + "checkout_token": { + "description": "Token for ACP checkout flow", + "type": "string" + }, + "checkout_url": { + "description": "ACP checkout initiation URL", + "format": "uri", + "type": "string" + }, + "product": { + "description": "Product details for checkout", + "type": "object" + } + }, + "type": "object" + }, + "errors": { + "items": { + "$ref": "../core/error.json" + }, + "type": "array" + }, + "ext": { + "$ref": "../core/ext.json" + }, + "follow_up": { + "additionalProperties": true, + "description": "Suggested follow-up actions", + "properties": { + "action": { + "enum": [ + "save_for_later", + "set_reminder", + "subscribe_updates", + "none" + ], + "type": "string" + }, + "data": { + "description": "Data for follow-up action", + "type": "object" + } + }, + "type": "object" + }, + "session_id": { + "description": "Terminated session identifier", + "type": "string" + }, + "terminated": { + "description": "Whether session was successfully terminated", + "type": "boolean" + } + }, + "required": [ + "session_id", + "terminated" + ], + "title": "SI Terminate Session Response", + "type": "object" +} \ No newline at end of file diff --git a/schemas/cache/sponsored-intelligence/si-ui-element.json b/schemas/cache/sponsored-intelligence/si-ui-element.json new file mode 100644 index 00000000..13014398 --- /dev/null +++ b/schemas/cache/sponsored-intelligence/si-ui-element.json @@ -0,0 +1,339 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "allOf": [ + { + "if": { + "properties": { + "type": { + "const": "text" + } + } + }, + "then": { + "properties": { + "data": { + "properties": { + "message": { + "description": "Text message content", + "type": "string" + } + }, + "required": [ + "message" + ], + "type": "object" + } + } + } + }, + { + "if": { + "properties": { + "type": { + "const": "link" + } + } + }, + "then": { + "properties": { + "data": { + "properties": { + "label": { + "description": "Link text", + "type": "string" + }, + "preview": { + "description": "Show link preview", + "type": "boolean" + }, + "url": { + "description": "Link URL", + "format": "uri", + "type": "string" + } + }, + "required": [ + "url", + "label" + ], + "type": "object" + } + } + } + }, + { + "if": { + "properties": { + "type": { + "const": "image" + } + } + }, + "then": { + "properties": { + "data": { + "properties": { + "alt": { + "description": "Alt text", + "type": "string" + }, + "caption": { + "description": "Image caption", + "type": "string" + }, + "url": { + "description": "Image URL", + "format": "uri", + "type": "string" + } + }, + "required": [ + "url", + "alt" + ], + "type": "object" + } + } + } + }, + { + "if": { + "properties": { + "type": { + "const": "product_card" + } + } + }, + "then": { + "properties": { + "data": { + "properties": { + "badge": { + "description": "Badge text (e.g., 'Free Upgrade')", + "type": "string" + }, + "cta": { + "properties": { + "action": { + "type": "string" + }, + "label": { + "type": "string" + } + }, + "type": "object" + }, + "description": { + "description": "Product description", + "type": "string" + }, + "image_url": { + "description": "Product image", + "format": "uri", + "type": "string" + }, + "price": { + "description": "Price display string", + "type": "string" + }, + "subtitle": { + "description": "Product subtitle", + "type": "string" + }, + "title": { + "description": "Product title", + "type": "string" + } + }, + "required": [ + "title", + "price" + ], + "type": "object" + } + } + } + }, + { + "if": { + "properties": { + "type": { + "const": "carousel" + } + } + }, + "then": { + "properties": { + "data": { + "properties": { + "items": { + "description": "Carousel items (product cards or images)", + "items": { + "type": "object" + }, + "type": "array" + }, + "title": { + "description": "Carousel title", + "type": "string" + } + }, + "required": [ + "items" + ], + "type": "object" + } + } + } + }, + { + "if": { + "properties": { + "type": { + "const": "action_button" + } + } + }, + "then": { + "properties": { + "data": { + "properties": { + "action": { + "description": "Action identifier (e.g., 'acp_checkout')", + "type": "string" + }, + "label": { + "description": "Button label", + "type": "string" + }, + "payload": { + "description": "Action payload", + "type": "object" + } + }, + "required": [ + "label", + "action" + ], + "type": "object" + } + } + } + }, + { + "if": { + "properties": { + "type": { + "const": "app_handoff" + } + } + }, + "then": { + "properties": { + "apps": { + "additionalProperties": { + "properties": { + "app_id": { + "type": "string" + }, + "deep_link": { + "type": "string" + }, + "url": { + "format": "uri", + "type": "string" + } + }, + "type": "object" + }, + "description": "Platform-specific app handoff targets", + "type": "object" + } + } + } + }, + { + "if": { + "properties": { + "type": { + "const": "integration_actions" + } + } + }, + "then": { + "properties": { + "data": { + "properties": { + "actions": { + "description": "Available integration actions", + "items": { + "properties": { + "highlighted": { + "description": "Whether this action should be visually emphasized", + "type": "boolean" + }, + "label": { + "description": "User-facing button label", + "type": "string" + }, + "type": { + "description": "Integration type", + "enum": [ + "mcp", + "a2a" + ], + "type": "string" + }, + "url": { + "description": "URL for the integration endpoint", + "format": "uri", + "type": "string" + } + }, + "required": [ + "type", + "label" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "actions" + ], + "type": "object" + } + } + } + } + ], + "description": "Standard visual component that brand returns and host renders", + "properties": { + "data": { + "additionalProperties": true, + "description": "Component-specific data", + "type": "object" + }, + "type": { + "description": "Component type", + "enum": [ + "text", + "link", + "image", + "product_card", + "carousel", + "action_button", + "app_handoff", + "integration_actions" + ], + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "SI UI Element", + "type": "object" +} \ No newline at end of file diff --git a/scripts/generate_ergonomic_coercion.py b/scripts/generate_ergonomic_coercion.py index 52d6bd6e..2f80cb37 100644 --- a/scripts/generate_ergonomic_coercion.py +++ b/scripts/generate_ergonomic_coercion.py @@ -48,8 +48,8 @@ # Nested types that also need coercion NESTED_TYPES_TO_ANALYZE = [ ("Sort", "media_buy.list_creatives_request"), - ("Packages", "media_buy.update_media_buy_request"), - ("Packages1", "media_buy.update_media_buy_request"), + ("PackageUpdate1", "media_buy.package_update"), + ("PackageUpdate2", "media_buy.package_update"), ] # Types that should get subclass_list coercion (for list variance) @@ -228,7 +228,7 @@ def generate_code() -> str: from adcp.types.generated_poc.media_buy.list_creatives_request import ListCreativesRequest, Sort from adcp.types.generated_poc.media_buy.list_creatives_response import ListCreativesResponse from adcp.types.generated_poc.media_buy.package_request import PackageRequest - from adcp.types.generated_poc.media_buy.update_media_buy_request import Packages, Packages1 + from adcp.types.generated_poc.media_buy.package_update import PackageUpdate1, PackageUpdate2 # Map names to classes request_classes = { @@ -249,8 +249,8 @@ def generate_code() -> str: nested_classes = { "Sort": Sort, - "Packages": Packages, - "Packages1": Packages1, + "PackageUpdate1": PackageUpdate1, + "PackageUpdate2": PackageUpdate2, } # Analyze all types @@ -364,9 +364,9 @@ def generate_code() -> str: lines.append(" Sort,") lines.append(")") lines.append("from adcp.types.generated_poc.media_buy.package_request import PackageRequest") - lines.append("from adcp.types.generated_poc.media_buy.update_media_buy_request import (") - lines.append(" Packages,") - lines.append(" Packages1,") + lines.append("from adcp.types.generated_poc.media_buy.package_update import (") + lines.append(" PackageUpdate1,") + lines.append(" PackageUpdate2,") lines.append(")") # Add response type imports @@ -409,8 +409,8 @@ def generate_code() -> str: "GetProductsRequest", "PackageRequest", "CreateMediaBuyRequest", - "Packages", - "Packages1", + "PackageUpdate1", + "PackageUpdate2", # Response types "GetProductsResponse", "ListCreativesResponse", @@ -503,7 +503,7 @@ def generate_code() -> str: lines.append(f" {type_name}.model_rebuild(force=True)") lines.append("") - # Handle Packages and Packages1 together if they have same coercions + # Handle PackageUpdate1 and PackageUpdate2 together if they have same coercions # (they're already handled in the loop above) # Add helper function diff --git a/src/adcp/ADCP_VERSION b/src/adcp/ADCP_VERSION index e70b4523..a0f9a4b4 100644 --- a/src/adcp/ADCP_VERSION +++ b/src/adcp/ADCP_VERSION @@ -1 +1 @@ -2.6.0 +latest diff --git a/src/adcp/__init__.py b/src/adcp/__init__.py index 36a903f8..785b880d 100644 --- a/src/adcp/__init__.py +++ b/src/adcp/__init__.py @@ -152,9 +152,7 @@ PreviewCreativeManifestRequest, PreviewCreativeStaticResponse, PropertyId, - PropertyIdActivationKey, PropertyTag, - PropertyTagActivationKey, ProvidePerformanceFeedbackErrorResponse, ProvidePerformanceFeedbackSuccessResponse, PublisherPropertiesAll, @@ -379,9 +377,7 @@ def get_adcp_version() -> str: "PreviewCreativeStaticResponse", "PreviewCreativeInteractiveResponse", "PropertyId", - "PropertyIdActivationKey", "PropertyTag", - "PropertyTagActivationKey", "ProvidePerformanceFeedbackSuccessResponse", "ProvidePerformanceFeedbackErrorResponse", "PublisherPropertiesAll", diff --git a/src/adcp/__main__.py b/src/adcp/__main__.py index 3a1277f0..7c238025 100644 --- a/src/adcp/__main__.py +++ b/src/adcp/__main__.py @@ -157,21 +157,46 @@ async def execute_tool( # Types are filled at runtime to avoid circular imports # Special case: list_tools and get_info take no parameters (None means no request type) TOOL_DISPATCH: dict[str, tuple[str, type | None]] = { + # Protocol introspection "list_tools": ("list_tools", None), # Protocol introspection - no request type "get_info": ("get_info", None), # Agent info - no request type + # Core catalog "get_products": ("get_products", None), "list_creative_formats": ("list_creative_formats", None), "preview_creative": ("preview_creative", None), "build_creative": ("build_creative", None), "sync_creatives": ("sync_creatives", None), "list_creatives": ("list_creatives", None), + # Media buy "create_media_buy": ("create_media_buy", None), "update_media_buy": ("update_media_buy", None), "get_media_buy_delivery": ("get_media_buy_delivery", None), "list_authorized_properties": ("list_authorized_properties", None), + # Signals "get_signals": ("get_signals", None), "activate_signal": ("activate_signal", None), "provide_performance_feedback": ("provide_performance_feedback", None), + # V3 Protocol Discovery + "get_adcp_capabilities": ("get_adcp_capabilities", None), + # V3 Content Standards + "create_content_standards": ("create_content_standards", None), + "get_content_standards": ("get_content_standards", None), + "list_content_standards": ("list_content_standards", None), + "update_content_standards": ("update_content_standards", None), + "calibrate_content": ("calibrate_content", None), + "validate_content_delivery": ("validate_content_delivery", None), + "get_media_buy_artifacts": ("get_media_buy_artifacts", None), + # V3 Sponsored Intelligence + "si_get_offering": ("si_get_offering", None), + "si_initiate_session": ("si_initiate_session", None), + "si_send_message": ("si_send_message", None), + "si_terminate_session": ("si_terminate_session", None), + # V3 Governance (Property Lists) + "create_property_list": ("create_property_list", None), + "get_property_list": ("get_property_list", None), + "list_property_lists": ("list_property_lists", None), + "update_property_list": ("update_property_list", None), + "delete_property_list": ("delete_property_list", None), } @@ -221,6 +246,66 @@ async def _dispatch_tool(client: ADCPClient, tool_name: str, payload: dict[str, "provide_performance_feedback", gen.ProvidePerformanceFeedbackRequest, ) + # V3 Protocol Discovery + TOOL_DISPATCH["get_adcp_capabilities"] = ( + "get_adcp_capabilities", + gen.GetAdcpCapabilitiesRequest, + ) + # V3 Content Standards + TOOL_DISPATCH["create_content_standards"] = ( + "create_content_standards", + gen.CreateContentStandardsRequest, + ) + TOOL_DISPATCH["get_content_standards"] = ( + "get_content_standards", + gen.GetContentStandardsRequest, + ) + TOOL_DISPATCH["list_content_standards"] = ( + "list_content_standards", + gen.ListContentStandardsRequest, + ) + TOOL_DISPATCH["update_content_standards"] = ( + "update_content_standards", + gen.UpdateContentStandardsRequest, + ) + TOOL_DISPATCH["calibrate_content"] = ("calibrate_content", gen.CalibrateContentRequest) + TOOL_DISPATCH["validate_content_delivery"] = ( + "validate_content_delivery", + gen.ValidateContentDeliveryRequest, + ) + TOOL_DISPATCH["get_media_buy_artifacts"] = ( + "get_media_buy_artifacts", + gen.GetMediaBuyArtifactsRequest, + ) + # V3 Sponsored Intelligence + TOOL_DISPATCH["si_get_offering"] = ("si_get_offering", gen.SiGetOfferingRequest) + TOOL_DISPATCH["si_initiate_session"] = ( + "si_initiate_session", + gen.SiInitiateSessionRequest, + ) + TOOL_DISPATCH["si_send_message"] = ("si_send_message", gen.SiSendMessageRequest) + TOOL_DISPATCH["si_terminate_session"] = ( + "si_terminate_session", + gen.SiTerminateSessionRequest, + ) + # V3 Governance (Property Lists) + TOOL_DISPATCH["create_property_list"] = ( + "create_property_list", + gen.CreatePropertyListRequest, + ) + TOOL_DISPATCH["get_property_list"] = ("get_property_list", gen.GetPropertyListRequest) + TOOL_DISPATCH["list_property_lists"] = ( + "list_property_lists", + gen.ListPropertyListsRequest, + ) + TOOL_DISPATCH["update_property_list"] = ( + "update_property_list", + gen.UpdatePropertyListRequest, + ) + TOOL_DISPATCH["delete_property_list"] = ( + "delete_property_list", + gen.DeletePropertyListRequest, + ) # Check if tool exists if tool_name not in TOOL_DISPATCH: @@ -451,6 +536,11 @@ def main() -> None: print(" adcp myagent list_tools") print(' adcp myagent get_products \'{"brief":"TV ads"}\'') print(" adcp https://agent.example.com list_tools") + print("\nV3 Protocol Examples:") + print(" adcp myagent get_adcp_capabilities") + print(" adcp cs-agent calibrate_content '{\"content_standards_id\":\"cs-123\"}'") + print(" adcp si-agent si_get_offering") + print(" adcp gov-agent list_property_lists") sys.exit(0) # Handle configuration commands diff --git a/src/adcp/client.py b/src/adcp/client.py index f338b3c1..9449edb0 100644 --- a/src/adcp/client.py +++ b/src/adcp/client.py @@ -47,6 +47,116 @@ UpdateMediaBuyRequest, UpdateMediaBuyResponse, ) + +# V3 Protocol Discovery types +from adcp.types.generated_poc.protocol.get_adcp_capabilities_request import ( + GetAdcpCapabilitiesRequest, +) +from adcp.types.generated_poc.protocol.get_adcp_capabilities_response import ( + GetAdcpCapabilitiesResponse, +) + +# V3 Content Standards types +from adcp.types.generated_poc.content_standards.create_content_standards_request import ( + CreateContentStandardsRequest, +) +from adcp.types.generated_poc.content_standards.create_content_standards_response import ( + CreateContentStandardsResponse, +) +from adcp.types.generated_poc.content_standards.get_content_standards_request import ( + GetContentStandardsRequest, +) +from adcp.types.generated_poc.content_standards.get_content_standards_response import ( + GetContentStandardsResponse, +) +from adcp.types.generated_poc.content_standards.list_content_standards_request import ( + ListContentStandardsRequest, +) +from adcp.types.generated_poc.content_standards.list_content_standards_response import ( + ListContentStandardsResponse, +) +from adcp.types.generated_poc.content_standards.update_content_standards_request import ( + UpdateContentStandardsRequest, +) +from adcp.types.generated_poc.content_standards.update_content_standards_response import ( + UpdateContentStandardsResponse, +) +from adcp.types.generated_poc.content_standards.calibrate_content_request import ( + CalibrateContentRequest, +) +from adcp.types.generated_poc.content_standards.calibrate_content_response import ( + CalibrateContentResponse, +) +from adcp.types.generated_poc.content_standards.validate_content_delivery_request import ( + ValidateContentDeliveryRequest, +) +from adcp.types.generated_poc.content_standards.validate_content_delivery_response import ( + ValidateContentDeliveryResponse, +) +from adcp.types.generated_poc.content_standards.get_media_buy_artifacts_request import ( + GetMediaBuyArtifactsRequest, +) +from adcp.types.generated_poc.content_standards.get_media_buy_artifacts_response import ( + GetMediaBuyArtifactsResponse, +) + +# V3 Sponsored Intelligence types +from adcp.types.generated_poc.sponsored_intelligence.si_get_offering_request import ( + SiGetOfferingRequest, +) +from adcp.types.generated_poc.sponsored_intelligence.si_get_offering_response import ( + SiGetOfferingResponse, +) +from adcp.types.generated_poc.sponsored_intelligence.si_initiate_session_request import ( + SiInitiateSessionRequest, +) +from adcp.types.generated_poc.sponsored_intelligence.si_initiate_session_response import ( + SiInitiateSessionResponse, +) +from adcp.types.generated_poc.sponsored_intelligence.si_send_message_request import ( + SiSendMessageRequest, +) +from adcp.types.generated_poc.sponsored_intelligence.si_send_message_response import ( + SiSendMessageResponse, +) +from adcp.types.generated_poc.sponsored_intelligence.si_terminate_session_request import ( + SiTerminateSessionRequest, +) +from adcp.types.generated_poc.sponsored_intelligence.si_terminate_session_response import ( + SiTerminateSessionResponse, +) + +# V3 Governance (Property Lists) types +from adcp.types.generated_poc.property.create_property_list_request import ( + CreatePropertyListRequest, +) +from adcp.types.generated_poc.property.create_property_list_response import ( + CreatePropertyListResponse, +) +from adcp.types.generated_poc.property.get_property_list_request import ( + GetPropertyListRequest, +) +from adcp.types.generated_poc.property.get_property_list_response import ( + GetPropertyListResponse, +) +from adcp.types.generated_poc.property.list_property_lists_request import ( + ListPropertyListsRequest, +) +from adcp.types.generated_poc.property.list_property_lists_response import ( + ListPropertyListsResponse, +) +from adcp.types.generated_poc.property.update_property_list_request import ( + UpdatePropertyListRequest, +) +from adcp.types.generated_poc.property.update_property_list_response import ( + UpdatePropertyListResponse, +) +from adcp.types.generated_poc.property.delete_property_list_request import ( + DeletePropertyListRequest, +) +from adcp.types.generated_poc.property.delete_property_list_response import ( + DeletePropertyListResponse, +) from adcp.types.core import ( Activity, ActivityType, @@ -773,6 +883,761 @@ async def build_creative( return self.adapter._parse_response(raw_result, BuildCreativeResponse) + # ======================================================================== + # V3 Protocol Methods - Protocol Discovery + # ======================================================================== + + async def get_adcp_capabilities( + self, + request: GetAdcpCapabilitiesRequest, + ) -> TaskResult[GetAdcpCapabilitiesResponse]: + """ + Get AdCP capabilities from the agent. + + Queries the agent's supported AdCP features, protocol versions, and + domain-specific capabilities (media_buy, signals, sponsored_intelligence). + + Args: + request: Request parameters including optional protocol filters + + Returns: + TaskResult containing GetAdcpCapabilitiesResponse with: + - adcp: Core protocol version information + - supported_protocols: List of supported domain protocols + - media_buy: Media buy capabilities (if supported) + - sponsored_intelligence: SI capabilities (if supported) + - signals: Signals capabilities (if supported) + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="get_adcp_capabilities", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.get_adcp_capabilities(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="get_adcp_capabilities", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, GetAdcpCapabilitiesResponse) + + # ======================================================================== + # V3 Protocol Methods - Content Standards + # ======================================================================== + + async def create_content_standards( + self, + request: CreateContentStandardsRequest, + ) -> TaskResult[CreateContentStandardsResponse]: + """ + Create a new content standards configuration. + + Defines acceptable content contexts for ad placement using natural + language policy and optional calibration exemplars. + + Args: + request: Request parameters including policy and scope + + Returns: + TaskResult containing CreateContentStandardsResponse with standards_id + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="create_content_standards", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.create_content_standards(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="create_content_standards", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, CreateContentStandardsResponse) + + async def get_content_standards( + self, + request: GetContentStandardsRequest, + ) -> TaskResult[GetContentStandardsResponse]: + """ + Get a content standards configuration by ID. + + Args: + request: Request parameters including standards_id + + Returns: + TaskResult containing GetContentStandardsResponse + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="get_content_standards", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.get_content_standards(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="get_content_standards", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, GetContentStandardsResponse) + + async def list_content_standards( + self, + request: ListContentStandardsRequest, + ) -> TaskResult[ListContentStandardsResponse]: + """ + List content standards configurations. + + Args: + request: Request parameters including optional filters + + Returns: + TaskResult containing ListContentStandardsResponse + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="list_content_standards", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.list_content_standards(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="list_content_standards", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, ListContentStandardsResponse) + + async def update_content_standards( + self, + request: UpdateContentStandardsRequest, + ) -> TaskResult[UpdateContentStandardsResponse]: + """ + Update a content standards configuration. + + Args: + request: Request parameters including standards_id and updates + + Returns: + TaskResult containing UpdateContentStandardsResponse + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="update_content_standards", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.update_content_standards(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="update_content_standards", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, UpdateContentStandardsResponse) + + async def calibrate_content( + self, + request: CalibrateContentRequest, + ) -> TaskResult[CalibrateContentResponse]: + """ + Calibrate content against standards. + + Evaluates content (artifact or URL) against configured standards to + determine suitability for ad placement. + + Args: + request: Request parameters including content to evaluate + + Returns: + TaskResult containing CalibrateContentResponse with verdict + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="calibrate_content", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.calibrate_content(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="calibrate_content", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, CalibrateContentResponse) + + async def validate_content_delivery( + self, + request: ValidateContentDeliveryRequest, + ) -> TaskResult[ValidateContentDeliveryResponse]: + """ + Validate content delivery against standards. + + Validates that ad delivery records comply with content standards. + + Args: + request: Request parameters including delivery records + + Returns: + TaskResult containing ValidateContentDeliveryResponse + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="validate_content_delivery", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.validate_content_delivery(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="validate_content_delivery", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, ValidateContentDeliveryResponse) + + async def get_media_buy_artifacts( + self, + request: GetMediaBuyArtifactsRequest, + ) -> TaskResult[GetMediaBuyArtifactsResponse]: + """ + Get artifacts associated with a media buy. + + Retrieves content artifacts where ads were delivered for a media buy. + + Args: + request: Request parameters including media_buy_id + + Returns: + TaskResult containing GetMediaBuyArtifactsResponse + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="get_media_buy_artifacts", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.get_media_buy_artifacts(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="get_media_buy_artifacts", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, GetMediaBuyArtifactsResponse) + + # ======================================================================== + # V3 Protocol Methods - Sponsored Intelligence + # ======================================================================== + + async def si_get_offering( + self, + request: SiGetOfferingRequest, + ) -> TaskResult[SiGetOfferingResponse]: + """ + Get sponsored intelligence offering. + + Retrieves product/service offerings that can be presented in a + sponsored intelligence session. + + Args: + request: Request parameters including brand context + + Returns: + TaskResult containing SiGetOfferingResponse + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="si_get_offering", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.si_get_offering(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="si_get_offering", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, SiGetOfferingResponse) + + async def si_initiate_session( + self, + request: SiInitiateSessionRequest, + ) -> TaskResult[SiInitiateSessionResponse]: + """ + Initiate a sponsored intelligence session. + + Starts a conversational brand experience session with a user. + + Args: + request: Request parameters including identity and context + + Returns: + TaskResult containing SiInitiateSessionResponse with session_id + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="si_initiate_session", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.si_initiate_session(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="si_initiate_session", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, SiInitiateSessionResponse) + + async def si_send_message( + self, + request: SiSendMessageRequest, + ) -> TaskResult[SiSendMessageResponse]: + """ + Send a message in a sponsored intelligence session. + + Continues the conversation in an active SI session. + + Args: + request: Request parameters including session_id and message + + Returns: + TaskResult containing SiSendMessageResponse with brand response + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="si_send_message", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.si_send_message(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="si_send_message", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, SiSendMessageResponse) + + async def si_terminate_session( + self, + request: SiTerminateSessionRequest, + ) -> TaskResult[SiTerminateSessionResponse]: + """ + Terminate a sponsored intelligence session. + + Ends an active SI session, optionally with follow-up actions. + + Args: + request: Request parameters including session_id and termination context + + Returns: + TaskResult containing SiTerminateSessionResponse + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="si_terminate_session", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.si_terminate_session(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="si_terminate_session", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, SiTerminateSessionResponse) + + # ======================================================================== + # V3 Governance (Property Lists) Methods + # ======================================================================== + + async def create_property_list( + self, + request: CreatePropertyListRequest, + ) -> TaskResult[CreatePropertyListResponse]: + """ + Create a property list for governance filtering. + + Property lists define dynamic sets of properties based on filters, + brand manifests, and feature requirements. + + Args: + request: Request parameters for creating the property list + + Returns: + TaskResult containing CreatePropertyListResponse with list_id + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="create_property_list", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.create_property_list(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="create_property_list", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, CreatePropertyListResponse) + + async def get_property_list( + self, + request: GetPropertyListRequest, + ) -> TaskResult[GetPropertyListResponse]: + """ + Get a property list with optional resolution. + + When resolve=true, returns the list of resolved property identifiers. + Use this to get the actual properties that match the list's filters. + + Args: + request: Request parameters including list_id and resolve flag + + Returns: + TaskResult containing GetPropertyListResponse with identifiers + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="get_property_list", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.get_property_list(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="get_property_list", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, GetPropertyListResponse) + + async def list_property_lists( + self, + request: ListPropertyListsRequest, + ) -> TaskResult[ListPropertyListsResponse]: + """ + List property lists owned by a principal. + + Retrieves metadata for all property lists, optionally filtered + by principal or pagination parameters. + + Args: + request: Request parameters with optional filtering + + Returns: + TaskResult containing ListPropertyListsResponse + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="list_property_lists", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.list_property_lists(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="list_property_lists", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, ListPropertyListsResponse) + + async def update_property_list( + self, + request: UpdatePropertyListRequest, + ) -> TaskResult[UpdatePropertyListResponse]: + """ + Update a property list. + + Modifies the filters, brand manifest, or other parameters + of an existing property list. + + Args: + request: Request parameters with list_id and updates + + Returns: + TaskResult containing UpdatePropertyListResponse + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="update_property_list", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.update_property_list(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="update_property_list", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, UpdatePropertyListResponse) + + async def delete_property_list( + self, + request: DeletePropertyListRequest, + ) -> TaskResult[DeletePropertyListResponse]: + """ + Delete a property list. + + Removes a property list. Any active subscriptions to this list + will be terminated. + + Args: + request: Request parameters with list_id + + Returns: + TaskResult containing DeletePropertyListResponse + """ + operation_id = create_operation_id() + params = request.model_dump(exclude_none=True) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_REQUEST, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="delete_property_list", + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + raw_result = await self.adapter.delete_property_list(params) + + self._emit_activity( + Activity( + type=ActivityType.PROTOCOL_RESPONSE, + operation_id=operation_id, + agent_id=self.agent_config.id, + task_type="delete_property_list", + status=raw_result.status, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + ) + + return self.adapter._parse_response(raw_result, DeletePropertyListResponse) + async def list_tools(self) -> list[str]: """ List available tools from the agent. diff --git a/src/adcp/protocols/a2a.py b/src/adcp/protocols/a2a.py index 1331bb94..81bb2c67 100644 --- a/src/adcp/protocols/a2a.py +++ b/src/adcp/protocols/a2a.py @@ -593,3 +593,87 @@ async def get_agent_info(self) -> dict[str, Any]: agent_id=self.agent_config.id, agent_uri=self.agent_config.agent_uri, ) from e + + # ======================================================================== + # V3 Protocol Methods - Protocol Discovery + # ======================================================================== + + async def get_adcp_capabilities(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get AdCP capabilities from the agent.""" + return await self._call_a2a_tool("get_adcp_capabilities", params) + + # ======================================================================== + # V3 Protocol Methods - Content Standards + # ======================================================================== + + async def create_content_standards(self, params: dict[str, Any]) -> TaskResult[Any]: + """Create content standards configuration.""" + return await self._call_a2a_tool("create_content_standards", params) + + async def get_content_standards(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get content standards configuration.""" + return await self._call_a2a_tool("get_content_standards", params) + + async def list_content_standards(self, params: dict[str, Any]) -> TaskResult[Any]: + """List content standards configurations.""" + return await self._call_a2a_tool("list_content_standards", params) + + async def update_content_standards(self, params: dict[str, Any]) -> TaskResult[Any]: + """Update content standards configuration.""" + return await self._call_a2a_tool("update_content_standards", params) + + async def calibrate_content(self, params: dict[str, Any]) -> TaskResult[Any]: + """Calibrate content against standards.""" + return await self._call_a2a_tool("calibrate_content", params) + + async def validate_content_delivery(self, params: dict[str, Any]) -> TaskResult[Any]: + """Validate content delivery against standards.""" + return await self._call_a2a_tool("validate_content_delivery", params) + + async def get_media_buy_artifacts(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get artifacts associated with a media buy.""" + return await self._call_a2a_tool("get_media_buy_artifacts", params) + + # ======================================================================== + # V3 Protocol Methods - Sponsored Intelligence + # ======================================================================== + + async def si_get_offering(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get sponsored intelligence offering.""" + return await self._call_a2a_tool("si_get_offering", params) + + async def si_initiate_session(self, params: dict[str, Any]) -> TaskResult[Any]: + """Initiate sponsored intelligence session.""" + return await self._call_a2a_tool("si_initiate_session", params) + + async def si_send_message(self, params: dict[str, Any]) -> TaskResult[Any]: + """Send message in sponsored intelligence session.""" + return await self._call_a2a_tool("si_send_message", params) + + async def si_terminate_session(self, params: dict[str, Any]) -> TaskResult[Any]: + """Terminate sponsored intelligence session.""" + return await self._call_a2a_tool("si_terminate_session", params) + + # ======================================================================== + # V3 Protocol Methods - Governance (Property Lists) + # ======================================================================== + + async def create_property_list(self, params: dict[str, Any]) -> TaskResult[Any]: + """Create a property list for governance.""" + return await self._call_a2a_tool("create_property_list", params) + + async def get_property_list(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get a property list with optional resolution.""" + return await self._call_a2a_tool("get_property_list", params) + + async def list_property_lists(self, params: dict[str, Any]) -> TaskResult[Any]: + """List property lists.""" + return await self._call_a2a_tool("list_property_lists", params) + + async def update_property_list(self, params: dict[str, Any]) -> TaskResult[Any]: + """Update a property list.""" + return await self._call_a2a_tool("update_property_list", params) + + async def delete_property_list(self, params: dict[str, Any]) -> TaskResult[Any]: + """Delete a property list.""" + return await self._call_a2a_tool("delete_property_list", params) diff --git a/src/adcp/protocols/base.py b/src/adcp/protocols/base.py index bbbbf992..8ce0308d 100644 --- a/src/adcp/protocols/base.py +++ b/src/adcp/protocols/base.py @@ -188,3 +188,104 @@ async def close(self) -> None: Implementations should close any open connections, clients, or other resources. """ pass + + # ======================================================================== + # V3 Protocol Methods - Protocol Discovery + # ======================================================================== + + @abstractmethod + async def get_adcp_capabilities(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get AdCP capabilities from the agent.""" + pass + + # ======================================================================== + # V3 Protocol Methods - Content Standards + # ======================================================================== + + @abstractmethod + async def create_content_standards(self, params: dict[str, Any]) -> TaskResult[Any]: + """Create content standards configuration.""" + pass + + @abstractmethod + async def get_content_standards(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get content standards configuration.""" + pass + + @abstractmethod + async def list_content_standards(self, params: dict[str, Any]) -> TaskResult[Any]: + """List content standards configurations.""" + pass + + @abstractmethod + async def update_content_standards(self, params: dict[str, Any]) -> TaskResult[Any]: + """Update content standards configuration.""" + pass + + @abstractmethod + async def calibrate_content(self, params: dict[str, Any]) -> TaskResult[Any]: + """Calibrate content against standards.""" + pass + + @abstractmethod + async def validate_content_delivery(self, params: dict[str, Any]) -> TaskResult[Any]: + """Validate content delivery against standards.""" + pass + + @abstractmethod + async def get_media_buy_artifacts(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get artifacts associated with a media buy.""" + pass + + # ======================================================================== + # V3 Protocol Methods - Sponsored Intelligence + # ======================================================================== + + @abstractmethod + async def si_get_offering(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get sponsored intelligence offering.""" + pass + + @abstractmethod + async def si_initiate_session(self, params: dict[str, Any]) -> TaskResult[Any]: + """Initiate sponsored intelligence session.""" + pass + + @abstractmethod + async def si_send_message(self, params: dict[str, Any]) -> TaskResult[Any]: + """Send message in sponsored intelligence session.""" + pass + + @abstractmethod + async def si_terminate_session(self, params: dict[str, Any]) -> TaskResult[Any]: + """Terminate sponsored intelligence session.""" + pass + + # ======================================================================== + # V3 Protocol Methods - Governance (Property Lists) + # ======================================================================== + + @abstractmethod + async def create_property_list(self, params: dict[str, Any]) -> TaskResult[Any]: + """Create a property list for governance.""" + pass + + @abstractmethod + async def get_property_list(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get a property list with optional resolution.""" + pass + + @abstractmethod + async def list_property_lists(self, params: dict[str, Any]) -> TaskResult[Any]: + """List property lists.""" + pass + + @abstractmethod + async def update_property_list(self, params: dict[str, Any]) -> TaskResult[Any]: + """Update a property list.""" + pass + + @abstractmethod + async def delete_property_list(self, params: dict[str, Any]) -> TaskResult[Any]: + """Delete a property list.""" + pass diff --git a/src/adcp/protocols/mcp.py b/src/adcp/protocols/mcp.py index ac6c16b2..724d03ef 100644 --- a/src/adcp/protocols/mcp.py +++ b/src/adcp/protocols/mcp.py @@ -517,3 +517,87 @@ async def get_agent_info(self) -> dict[str, Any]: async def close(self) -> None: """Close the MCP session and clean up resources.""" await self._cleanup_failed_connection("during close") + + # ======================================================================== + # V3 Protocol Methods - Protocol Discovery + # ======================================================================== + + async def get_adcp_capabilities(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get AdCP capabilities from the agent.""" + return await self._call_mcp_tool("get_adcp_capabilities", params) + + # ======================================================================== + # V3 Protocol Methods - Content Standards + # ======================================================================== + + async def create_content_standards(self, params: dict[str, Any]) -> TaskResult[Any]: + """Create content standards configuration.""" + return await self._call_mcp_tool("create_content_standards", params) + + async def get_content_standards(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get content standards configuration.""" + return await self._call_mcp_tool("get_content_standards", params) + + async def list_content_standards(self, params: dict[str, Any]) -> TaskResult[Any]: + """List content standards configurations.""" + return await self._call_mcp_tool("list_content_standards", params) + + async def update_content_standards(self, params: dict[str, Any]) -> TaskResult[Any]: + """Update content standards configuration.""" + return await self._call_mcp_tool("update_content_standards", params) + + async def calibrate_content(self, params: dict[str, Any]) -> TaskResult[Any]: + """Calibrate content against standards.""" + return await self._call_mcp_tool("calibrate_content", params) + + async def validate_content_delivery(self, params: dict[str, Any]) -> TaskResult[Any]: + """Validate content delivery against standards.""" + return await self._call_mcp_tool("validate_content_delivery", params) + + async def get_media_buy_artifacts(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get artifacts associated with a media buy.""" + return await self._call_mcp_tool("get_media_buy_artifacts", params) + + # ======================================================================== + # V3 Protocol Methods - Sponsored Intelligence + # ======================================================================== + + async def si_get_offering(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get sponsored intelligence offering.""" + return await self._call_mcp_tool("si_get_offering", params) + + async def si_initiate_session(self, params: dict[str, Any]) -> TaskResult[Any]: + """Initiate sponsored intelligence session.""" + return await self._call_mcp_tool("si_initiate_session", params) + + async def si_send_message(self, params: dict[str, Any]) -> TaskResult[Any]: + """Send message in sponsored intelligence session.""" + return await self._call_mcp_tool("si_send_message", params) + + async def si_terminate_session(self, params: dict[str, Any]) -> TaskResult[Any]: + """Terminate sponsored intelligence session.""" + return await self._call_mcp_tool("si_terminate_session", params) + + # ======================================================================== + # V3 Protocol Methods - Governance (Property Lists) + # ======================================================================== + + async def create_property_list(self, params: dict[str, Any]) -> TaskResult[Any]: + """Create a property list for governance.""" + return await self._call_mcp_tool("create_property_list", params) + + async def get_property_list(self, params: dict[str, Any]) -> TaskResult[Any]: + """Get a property list with optional resolution.""" + return await self._call_mcp_tool("get_property_list", params) + + async def list_property_lists(self, params: dict[str, Any]) -> TaskResult[Any]: + """List property lists.""" + return await self._call_mcp_tool("list_property_lists", params) + + async def update_property_list(self, params: dict[str, Any]) -> TaskResult[Any]: + """Update a property list.""" + return await self._call_mcp_tool("update_property_list", params) + + async def delete_property_list(self, params: dict[str, Any]) -> TaskResult[Any]: + """Delete a property list.""" + return await self._call_mcp_tool("delete_property_list", params) diff --git a/src/adcp/server/__init__.py b/src/adcp/server/__init__.py new file mode 100644 index 00000000..bfd8544d --- /dev/null +++ b/src/adcp/server/__init__.py @@ -0,0 +1,49 @@ +"""ADCP Server Framework. + +Provides base classes and adapters for building ADCP-compliant servers/agents. +Supports selective protocol implementation via protocol-specific adapters. + +Examples: + # Content Standards agent (stubs media buy operations) + from adcp.server import ContentStandardsHandler, create_mcp_tools + + class MyContentHandler(ContentStandardsHandler): + async def create_content_standards(self, request): + # Implement your logic + pass + + # Register with MCP server + tools = create_mcp_tools(MyContentHandler()) +""" + +from __future__ import annotations + +from adcp.server.base import ( + ADCPHandler, + NotImplementedResponse, + ToolContext, + not_supported, +) +from adcp.server.content_standards import ContentStandardsHandler +from adcp.server.governance import GovernanceHandler +from adcp.server.mcp_tools import MCPToolSet, create_mcp_tools +from adcp.server.proposal import ProposalBuilder, ProposalNotSupported +from adcp.server.sponsored_intelligence import SponsoredIntelligenceHandler + +__all__ = [ + # Base classes + "ADCPHandler", + "ToolContext", + "NotImplementedResponse", + "not_supported", + # Protocol handlers + "ContentStandardsHandler", + "GovernanceHandler", + "SponsoredIntelligenceHandler", + # Proposal helpers + "ProposalBuilder", + "ProposalNotSupported", + # MCP integration + "MCPToolSet", + "create_mcp_tools", +] diff --git a/src/adcp/server/base.py b/src/adcp/server/base.py new file mode 100644 index 00000000..26fd0e30 --- /dev/null +++ b/src/adcp/server/base.py @@ -0,0 +1,366 @@ +"""Base classes for ADCP server implementations. + +Defines the ADCPHandler base class and utilities for building ADCP-compliant agents. +""" + +from __future__ import annotations + +from abc import ABC +from dataclasses import dataclass, field +from typing import Any + +from pydantic import BaseModel + +from adcp.types import Error + + +@dataclass +class ToolContext: + """Context passed to tool handlers. + + Contains metadata about the current request that may be useful + for logging, authorization, or other cross-cutting concerns. + """ + + request_id: str | None = None + caller_identity: str | None = None + metadata: dict[str, Any] = field(default_factory=dict) + + +class NotImplementedResponse(BaseModel): + """Standard response for operations not supported by this handler.""" + + supported: bool = False + reason: str = "This operation is not supported by this agent" + error: Error | None = None + + +def not_supported(reason: str = "This operation is not supported by this agent") -> NotImplementedResponse: + """Create a standard 'not supported' response. + + Use this to return from operations that your agent does not implement. + + Args: + reason: Human-readable explanation of why the operation is not supported + + Returns: + NotImplementedResponse with supported=False + """ + return NotImplementedResponse( + supported=False, + reason=reason, + error=Error( + code="NOT_SUPPORTED", + message=reason, + ), + ) + + +class ADCPHandler(ABC): + """Base class for ADCP operation handlers. + + Subclass this to implement ADCP operations. All operations have default + implementations that return 'not supported', allowing you to implement + only the operations your agent supports. + + For protocol-specific handlers, use: + - ContentStandardsHandler: For content standards agents + - SponsoredIntelligenceHandler: For sponsored intelligence agents + """ + + # ======================================================================== + # Core Catalog Operations + # ======================================================================== + + async def get_products( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Get advertising products. + + Override this to provide product catalog functionality. + """ + return not_supported("get_products is not implemented by this agent") + + async def list_creative_formats( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """List supported creative formats. + + Override this to provide creative format information. + """ + return not_supported("list_creative_formats is not implemented by this agent") + + async def list_authorized_properties( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """List authorized properties. + + Override this to provide property authorization information. + """ + return not_supported("list_authorized_properties is not implemented by this agent") + + # ======================================================================== + # Creative Operations + # ======================================================================== + + async def sync_creatives( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Sync creatives. + + Override this to handle creative synchronization. + """ + return not_supported("sync_creatives is not implemented by this agent") + + async def list_creatives( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """List creatives. + + Override this to list synced creatives. + """ + return not_supported("list_creatives is not implemented by this agent") + + async def build_creative( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Build a creative. + + Override this to build creatives from assets. + """ + return not_supported("build_creative is not implemented by this agent") + + # ======================================================================== + # Media Buy Operations + # ======================================================================== + + async def create_media_buy( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Create a media buy. + + Override this to handle media buy creation. + """ + return not_supported("create_media_buy is not implemented by this agent") + + async def update_media_buy( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Update a media buy. + + Override this to handle media buy updates. + """ + return not_supported("update_media_buy is not implemented by this agent") + + async def get_media_buy_delivery( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Get media buy delivery metrics. + + Override this to provide delivery reporting. + """ + return not_supported("get_media_buy_delivery is not implemented by this agent") + + # ======================================================================== + # Signal Operations + # ======================================================================== + + async def get_signals( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Get available signals. + + Override this to provide signal catalog. + """ + return not_supported("get_signals is not implemented by this agent") + + async def activate_signal( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Activate a signal. + + Override this to handle signal activation. + """ + return not_supported("activate_signal is not implemented by this agent") + + # ======================================================================== + # Feedback Operations + # ======================================================================== + + async def provide_performance_feedback( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Provide performance feedback. + + Override this to handle performance feedback ingestion. + """ + return not_supported("provide_performance_feedback is not implemented by this agent") + + # ======================================================================== + # V3 Protocol Discovery + # ======================================================================== + + async def get_adcp_capabilities( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Get ADCP capabilities. + + Override this to advertise your agent's capabilities. + """ + return not_supported("get_adcp_capabilities is not implemented by this agent") + + # ======================================================================== + # V3 Content Standards Operations + # ======================================================================== + + async def create_content_standards( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Create content standards configuration. + + Override this in ContentStandardsHandler subclasses. + """ + return not_supported("create_content_standards is not implemented by this agent") + + async def get_content_standards( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Get content standards configuration. + + Override this in ContentStandardsHandler subclasses. + """ + return not_supported("get_content_standards is not implemented by this agent") + + async def list_content_standards( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """List content standards configurations. + + Override this in ContentStandardsHandler subclasses. + """ + return not_supported("list_content_standards is not implemented by this agent") + + async def update_content_standards( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Update content standards configuration. + + Override this in ContentStandardsHandler subclasses. + """ + return not_supported("update_content_standards is not implemented by this agent") + + async def calibrate_content( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Calibrate content against standards. + + Override this in ContentStandardsHandler subclasses. + """ + return not_supported("calibrate_content is not implemented by this agent") + + async def validate_content_delivery( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Validate content delivery against standards. + + Override this in ContentStandardsHandler subclasses. + """ + return not_supported("validate_content_delivery is not implemented by this agent") + + async def get_media_buy_artifacts( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Get artifacts associated with a media buy. + + Override this in ContentStandardsHandler subclasses. + """ + return not_supported("get_media_buy_artifacts is not implemented by this agent") + + # ======================================================================== + # V3 Sponsored Intelligence Operations + # ======================================================================== + + async def si_get_offering( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Get sponsored intelligence offering. + + Override this in SponsoredIntelligenceHandler subclasses. + """ + return not_supported("si_get_offering is not implemented by this agent") + + async def si_initiate_session( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Initiate sponsored intelligence session. + + Override this in SponsoredIntelligenceHandler subclasses. + """ + return not_supported("si_initiate_session is not implemented by this agent") + + async def si_send_message( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Send message in sponsored intelligence session. + + Override this in SponsoredIntelligenceHandler subclasses. + """ + return not_supported("si_send_message is not implemented by this agent") + + async def si_terminate_session( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Terminate sponsored intelligence session. + + Override this in SponsoredIntelligenceHandler subclasses. + """ + return not_supported("si_terminate_session is not implemented by this agent") + + # ======================================================================== + # V3 Governance (Property Lists) Operations + # ======================================================================== + + async def create_property_list( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Create a property list for governance filtering. + + Override this in GovernanceHandler subclasses. + """ + return not_supported("create_property_list is not implemented by this agent") + + async def get_property_list( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Get a property list with optional resolution. + + Override this in GovernanceHandler subclasses. + """ + return not_supported("get_property_list is not implemented by this agent") + + async def list_property_lists( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """List property lists. + + Override this in GovernanceHandler subclasses. + """ + return not_supported("list_property_lists is not implemented by this agent") + + async def update_property_list( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Update a property list. + + Override this in GovernanceHandler subclasses. + """ + return not_supported("update_property_list is not implemented by this agent") + + async def delete_property_list( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> Any: + """Delete a property list. + + Override this in GovernanceHandler subclasses. + """ + return not_supported("delete_property_list is not implemented by this agent") diff --git a/src/adcp/server/content_standards.py b/src/adcp/server/content_standards.py new file mode 100644 index 00000000..af7469ea --- /dev/null +++ b/src/adcp/server/content_standards.py @@ -0,0 +1,369 @@ +"""Content Standards protocol handler. + +Provides a base class for implementing Content Standards agents. +Non-Content-Standards operations return 'not supported' by default. +""" + +from __future__ import annotations + +from abc import abstractmethod +from typing import Any + +from adcp.server.base import ADCPHandler, NotImplementedResponse, ToolContext, not_supported +from adcp.types import ( + CalibrateContentRequest, + CalibrateContentResponse, + ContentStandards, + CreateContentStandardsRequest, + CreateContentStandardsResponse, + GetContentStandardsRequest, + GetContentStandardsResponse, + GetMediaBuyArtifactsRequest, + GetMediaBuyArtifactsResponse, + ListContentStandardsRequest, + ListContentStandardsResponse, + UpdateContentStandardsRequest, + UpdateContentStandardsResponse, + ValidateContentDeliveryRequest, + ValidateContentDeliveryResponse, +) + + +class ContentStandardsHandler(ADCPHandler): + """Handler for Content Standards protocol. + + Subclass this to implement a Content Standards agent. All Content Standards + operations are abstract and must be implemented. Non-Content-Standards + operations (get_products, create_media_buy, etc.) return 'not supported'. + + Example: + class MyContentStandardsHandler(ContentStandardsHandler): + async def create_content_standards( + self, + request: CreateContentStandardsRequest, + context: ToolContext | None = None + ) -> CreateContentStandardsResponse: + # Your implementation + return CreateContentStandardsResponse(...) + """ + + # ======================================================================== + # Content Standards Operations - MUST be implemented + # ======================================================================== + + @abstractmethod + async def create_content_standards( + self, + request: CreateContentStandardsRequest, + context: ToolContext | None = None, + ) -> CreateContentStandardsResponse: + """Create content standards configuration. + + Must be implemented by Content Standards agents. + + Args: + request: Content standards creation request + context: Optional tool context + + Returns: + Content standards creation response + """ + ... + + @abstractmethod + async def get_content_standards( + self, + request: GetContentStandardsRequest, + context: ToolContext | None = None, + ) -> GetContentStandardsResponse: + """Get content standards configuration. + + Must be implemented by Content Standards agents. + + Args: + request: Content standards retrieval request + context: Optional tool context + + Returns: + Content standards response + """ + ... + + @abstractmethod + async def list_content_standards( + self, + request: ListContentStandardsRequest, + context: ToolContext | None = None, + ) -> ListContentStandardsResponse: + """List content standards configurations. + + Must be implemented by Content Standards agents. + + Args: + request: List content standards request + context: Optional tool context + + Returns: + List of content standards + """ + ... + + @abstractmethod + async def update_content_standards( + self, + request: UpdateContentStandardsRequest, + context: ToolContext | None = None, + ) -> UpdateContentStandardsResponse: + """Update content standards configuration. + + Must be implemented by Content Standards agents. + + Args: + request: Content standards update request + context: Optional tool context + + Returns: + Updated content standards response + """ + ... + + @abstractmethod + async def calibrate_content( + self, + request: CalibrateContentRequest, + context: ToolContext | None = None, + ) -> CalibrateContentResponse: + """Calibrate content against standards. + + Must be implemented by Content Standards agents. + + Args: + request: Calibration request with content to evaluate + context: Optional tool context + + Returns: + Calibration response with scores and feedback + """ + ... + + @abstractmethod + async def validate_content_delivery( + self, + request: ValidateContentDeliveryRequest, + context: ToolContext | None = None, + ) -> ValidateContentDeliveryResponse: + """Validate content delivery against standards. + + Must be implemented by Content Standards agents. + + Args: + request: Validation request with delivery data + context: Optional tool context + + Returns: + Validation response + """ + ... + + @abstractmethod + async def get_media_buy_artifacts( + self, + request: GetMediaBuyArtifactsRequest, + context: ToolContext | None = None, + ) -> GetMediaBuyArtifactsResponse: + """Get artifacts associated with a media buy. + + Must be implemented by Content Standards agents. + + Args: + request: Artifacts retrieval request + context: Optional tool context + + Returns: + Media buy artifacts response + """ + ... + + # ======================================================================== + # Non-Content-Standards Operations - Return 'not supported' + # ======================================================================== + + async def get_products( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "get_products is not supported by Content Standards agents. " + "This agent handles content calibration and validation, not product catalog operations." + ) + + async def list_creative_formats( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "list_creative_formats is not supported by Content Standards agents." + ) + + async def list_authorized_properties( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "list_authorized_properties is not supported by Content Standards agents." + ) + + async def sync_creatives( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "sync_creatives is not supported by Content Standards agents." + ) + + async def list_creatives( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "list_creatives is not supported by Content Standards agents." + ) + + async def build_creative( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "build_creative is not supported by Content Standards agents." + ) + + async def create_media_buy( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "create_media_buy is not supported by Content Standards agents. " + "This agent handles content calibration and validation, not media buying." + ) + + async def update_media_buy( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "update_media_buy is not supported by Content Standards agents." + ) + + async def get_media_buy_delivery( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "get_media_buy_delivery is not supported by Content Standards agents." + ) + + async def get_signals( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "get_signals is not supported by Content Standards agents." + ) + + async def activate_signal( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "activate_signal is not supported by Content Standards agents." + ) + + async def provide_performance_feedback( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "provide_performance_feedback is not supported by Content Standards agents." + ) + + # ======================================================================== + # V3 Sponsored Intelligence - Not supported + # ======================================================================== + + async def si_get_offering( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "si_get_offering is not supported by Content Standards agents. " + "Use a Sponsored Intelligence agent for SI operations." + ) + + async def si_initiate_session( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "si_initiate_session is not supported by Content Standards agents." + ) + + async def si_send_message( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "si_send_message is not supported by Content Standards agents." + ) + + async def si_terminate_session( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "si_terminate_session is not supported by Content Standards agents." + ) + + # ======================================================================== + # V3 Governance (Property Lists) - Not supported + # ======================================================================== + + async def create_property_list( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "create_property_list is not supported by Content Standards agents. " + "Use a Governance agent for property list operations." + ) + + async def get_property_list( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "get_property_list is not supported by Content Standards agents." + ) + + async def list_property_lists( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "list_property_lists is not supported by Content Standards agents." + ) + + async def update_property_list( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "update_property_list is not supported by Content Standards agents." + ) + + async def delete_property_list( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Content Standards agents.""" + return not_supported( + "delete_property_list is not supported by Content Standards agents." + ) diff --git a/src/adcp/server/governance.py b/src/adcp/server/governance.py new file mode 100644 index 00000000..2f05d4d8 --- /dev/null +++ b/src/adcp/server/governance.py @@ -0,0 +1,351 @@ +"""Governance protocol handler. + +Provides a base class for implementing Governance agents that manage +property lists for brand safety, compliance, and quality filtering. +""" + +from __future__ import annotations + +from abc import abstractmethod +from typing import Any + +from adcp.server.base import ADCPHandler, NotImplementedResponse, ToolContext, not_supported +from adcp.types import ( + CreatePropertyListRequest, + CreatePropertyListResponse, + DeletePropertyListRequest, + DeletePropertyListResponse, + GetPropertyListRequest, + GetPropertyListResponse, + ListPropertyListsRequest, + ListPropertyListsResponse, + UpdatePropertyListRequest, + UpdatePropertyListResponse, +) + + +class GovernanceHandler(ADCPHandler): + """Handler for Governance protocol (Property Lists). + + Subclass this to implement a Governance agent that manages property lists + for brand safety, compliance scoring, and quality filtering. + + All property list operations are abstract and must be implemented. + Non-governance operations (get_products, create_media_buy, etc.) + return 'not supported'. + + Example: + class MyGovernanceHandler(GovernanceHandler): + async def create_property_list( + self, + request: CreatePropertyListRequest, + context: ToolContext | None = None + ) -> CreatePropertyListResponse: + # Store the list definition + list_id = generate_id() + # ... + return CreatePropertyListResponse(list=PropertyList(...)) + """ + + # ======================================================================== + # Governance Operations - MUST be implemented + # ======================================================================== + + @abstractmethod + async def create_property_list( + self, + request: CreatePropertyListRequest, + context: ToolContext | None = None, + ) -> CreatePropertyListResponse: + """Create a property list for governance filtering. + + Must be implemented by Governance agents. + + Args: + request: Property list creation request with filters and brand manifest + context: Optional tool context + + Returns: + Response with created property list metadata + """ + ... + + @abstractmethod + async def get_property_list( + self, + request: GetPropertyListRequest, + context: ToolContext | None = None, + ) -> GetPropertyListResponse: + """Get a property list with optional resolution. + + Must be implemented by Governance agents. + + When resolve=true, evaluates filters and returns matching property + identifiers. Otherwise returns only metadata. + + Args: + request: Request with list_id and optional resolve flag + context: Optional tool context + + Returns: + Response with list metadata and optionally resolved identifiers + """ + ... + + @abstractmethod + async def list_property_lists( + self, + request: ListPropertyListsRequest, + context: ToolContext | None = None, + ) -> ListPropertyListsResponse: + """List property lists. + + Must be implemented by Governance agents. + + Args: + request: Request with optional filtering and pagination + context: Optional tool context + + Returns: + Response with array of property list metadata + """ + ... + + @abstractmethod + async def update_property_list( + self, + request: UpdatePropertyListRequest, + context: ToolContext | None = None, + ) -> UpdatePropertyListResponse: + """Update a property list. + + Must be implemented by Governance agents. + + Args: + request: Request with list_id and updates + context: Optional tool context + + Returns: + Response with updated property list + """ + ... + + @abstractmethod + async def delete_property_list( + self, + request: DeletePropertyListRequest, + context: ToolContext | None = None, + ) -> DeletePropertyListResponse: + """Delete a property list. + + Must be implemented by Governance agents. + + Args: + request: Request with list_id + context: Optional tool context + + Returns: + Response confirming deletion + """ + ... + + # ======================================================================== + # Non-Governance Operations - Return 'not supported' + # ======================================================================== + + async def get_products( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "get_products is not supported by Governance agents. " + "This agent manages property lists for filtering, not product catalogs." + ) + + async def list_creative_formats( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "list_creative_formats is not supported by Governance agents." + ) + + async def list_authorized_properties( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "list_authorized_properties is not supported by Governance agents. " + "Use get_property_list with resolve=true instead." + ) + + async def sync_creatives( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "sync_creatives is not supported by Governance agents." + ) + + async def list_creatives( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "list_creatives is not supported by Governance agents." + ) + + async def build_creative( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "build_creative is not supported by Governance agents." + ) + + async def create_media_buy( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "create_media_buy is not supported by Governance agents. " + "This agent manages property lists, not media buying." + ) + + async def update_media_buy( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "update_media_buy is not supported by Governance agents." + ) + + async def get_media_buy_delivery( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "get_media_buy_delivery is not supported by Governance agents." + ) + + async def get_signals( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "get_signals is not supported by Governance agents." + ) + + async def activate_signal( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "activate_signal is not supported by Governance agents." + ) + + async def provide_performance_feedback( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "provide_performance_feedback is not supported by Governance agents." + ) + + # ======================================================================== + # V3 Content Standards - Not supported + # ======================================================================== + + async def create_content_standards( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "create_content_standards is not supported by Governance agents. " + "Use a Content Standards agent for content calibration." + ) + + async def get_content_standards( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "get_content_standards is not supported by Governance agents." + ) + + async def list_content_standards( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "list_content_standards is not supported by Governance agents." + ) + + async def update_content_standards( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "update_content_standards is not supported by Governance agents." + ) + + async def calibrate_content( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "calibrate_content is not supported by Governance agents." + ) + + async def validate_content_delivery( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "validate_content_delivery is not supported by Governance agents." + ) + + async def get_media_buy_artifacts( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "get_media_buy_artifacts is not supported by Governance agents." + ) + + # ======================================================================== + # V3 Sponsored Intelligence - Not supported + # ======================================================================== + + async def si_get_offering( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "si_get_offering is not supported by Governance agents. " + "Use a Sponsored Intelligence agent for SI operations." + ) + + async def si_initiate_session( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "si_initiate_session is not supported by Governance agents." + ) + + async def si_send_message( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "si_send_message is not supported by Governance agents." + ) + + async def si_terminate_session( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Governance agents.""" + return not_supported( + "si_terminate_session is not supported by Governance agents." + ) diff --git a/src/adcp/server/mcp_tools.py b/src/adcp/server/mcp_tools.py new file mode 100644 index 00000000..52523764 --- /dev/null +++ b/src/adcp/server/mcp_tools.py @@ -0,0 +1,470 @@ +"""MCP server integration helpers. + +Provides utilities for registering ADCP handlers with MCP servers. +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Callable + +from adcp.server.base import ADCPHandler, ToolContext + +if TYPE_CHECKING: + pass + + +# Tool definitions for all ADCP operations +ADCP_TOOL_DEFINITIONS: list[dict[str, Any]] = [ + # Core Catalog Operations + { + "name": "get_products", + "description": "Get advertising products from the catalog", + "inputSchema": { + "type": "object", + "properties": { + "context": {"type": "object"}, + "filters": {"type": "object"}, + "pagination": {"type": "object"}, + "fields": {"type": "array", "items": {"type": "string"}}, + }, + }, + }, + { + "name": "list_creative_formats", + "description": "List supported creative formats", + "inputSchema": { + "type": "object", + "properties": { + "type": {"type": "string"}, + "format_id": {"type": "string"}, + "pagination": {"type": "object"}, + }, + }, + }, + { + "name": "list_authorized_properties", + "description": "List properties authorized for ad placement", + "inputSchema": { + "type": "object", + "properties": { + "filters": {"type": "object"}, + "pagination": {"type": "object"}, + }, + }, + }, + # Creative Operations + { + "name": "sync_creatives", + "description": "Sync creatives to the agent", + "inputSchema": { + "type": "object", + "properties": { + "creatives": {"type": "array"}, + }, + "required": ["creatives"], + }, + }, + { + "name": "list_creatives", + "description": "List synced creatives", + "inputSchema": { + "type": "object", + "properties": { + "filters": {"type": "object"}, + "pagination": {"type": "object"}, + "fields": {"type": "array", "items": {"type": "string"}}, + }, + }, + }, + { + "name": "build_creative", + "description": "Build a creative from assets", + "inputSchema": { + "type": "object", + "properties": { + "format_id": {"type": "string"}, + "assets": {"type": "array"}, + }, + "required": ["format_id", "assets"], + }, + }, + # Media Buy Operations + { + "name": "create_media_buy", + "description": "Create a media buy from products", + "inputSchema": { + "type": "object", + "properties": { + "packages": {"type": "array"}, + "proposal_id": {"type": "string"}, + }, + }, + }, + { + "name": "update_media_buy", + "description": "Update an existing media buy", + "inputSchema": { + "type": "object", + "properties": { + "media_buy_id": {"type": "string"}, + "packages": {"type": "array"}, + }, + "required": ["media_buy_id"], + }, + }, + { + "name": "get_media_buy_delivery", + "description": "Get delivery metrics for a media buy", + "inputSchema": { + "type": "object", + "properties": { + "media_buy_id": {"type": "string"}, + "metrics": {"type": "array", "items": {"type": "string"}}, + }, + "required": ["media_buy_id"], + }, + }, + # Signal Operations + { + "name": "get_signals", + "description": "Get available signals", + "inputSchema": { + "type": "object", + "properties": { + "filters": {"type": "object"}, + "pagination": {"type": "object"}, + }, + }, + }, + { + "name": "activate_signal", + "description": "Activate a signal for use", + "inputSchema": { + "type": "object", + "properties": { + "signal_id": {"type": "string"}, + "activation_key": {"type": "string"}, + }, + "required": ["signal_id"], + }, + }, + # Feedback Operations + { + "name": "provide_performance_feedback", + "description": "Provide performance feedback", + "inputSchema": { + "type": "object", + "properties": { + "media_buy_id": {"type": "string"}, + "feedback": {"type": "object"}, + }, + "required": ["media_buy_id", "feedback"], + }, + }, + # V3 Protocol Discovery + { + "name": "get_adcp_capabilities", + "description": "Get ADCP capabilities supported by this agent", + "inputSchema": { + "type": "object", + "properties": {}, + }, + }, + # V3 Content Standards + { + "name": "create_content_standards", + "description": "Create content standards configuration", + "inputSchema": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "rules": {"type": "array"}, + }, + "required": ["name"], + }, + }, + { + "name": "get_content_standards", + "description": "Get content standards configuration", + "inputSchema": { + "type": "object", + "properties": { + "content_standards_id": {"type": "string"}, + }, + "required": ["content_standards_id"], + }, + }, + { + "name": "list_content_standards", + "description": "List content standards configurations", + "inputSchema": { + "type": "object", + "properties": { + "pagination": {"type": "object"}, + }, + }, + }, + { + "name": "update_content_standards", + "description": "Update content standards configuration", + "inputSchema": { + "type": "object", + "properties": { + "content_standards_id": {"type": "string"}, + "rules": {"type": "array"}, + }, + "required": ["content_standards_id"], + }, + }, + { + "name": "calibrate_content", + "description": "Calibrate content against standards", + "inputSchema": { + "type": "object", + "properties": { + "content_standards_id": {"type": "string"}, + "content": {"type": "object"}, + }, + "required": ["content_standards_id", "content"], + }, + }, + { + "name": "validate_content_delivery", + "description": "Validate content delivery against standards", + "inputSchema": { + "type": "object", + "properties": { + "content_standards_id": {"type": "string"}, + "delivery": {"type": "object"}, + }, + "required": ["content_standards_id", "delivery"], + }, + }, + { + "name": "get_media_buy_artifacts", + "description": "Get artifacts associated with a media buy", + "inputSchema": { + "type": "object", + "properties": { + "media_buy_id": {"type": "string"}, + }, + "required": ["media_buy_id"], + }, + }, + # V3 Sponsored Intelligence + { + "name": "si_get_offering", + "description": "Get sponsored intelligence offering", + "inputSchema": { + "type": "object", + "properties": {}, + }, + }, + { + "name": "si_initiate_session", + "description": "Initiate sponsored intelligence session", + "inputSchema": { + "type": "object", + "properties": { + "topic": {"type": "string"}, + "budget": {"type": "number"}, + }, + }, + }, + { + "name": "si_send_message", + "description": "Send message in sponsored intelligence session", + "inputSchema": { + "type": "object", + "properties": { + "session_id": {"type": "string"}, + "message": {"type": "string"}, + }, + "required": ["session_id", "message"], + }, + }, + { + "name": "si_terminate_session", + "description": "Terminate sponsored intelligence session", + "inputSchema": { + "type": "object", + "properties": { + "session_id": {"type": "string"}, + }, + "required": ["session_id"], + }, + }, + # V3 Governance (Property Lists) + { + "name": "create_property_list", + "description": "Create a property list for governance filtering", + "inputSchema": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "description": {"type": "string"}, + "base_properties": {"type": "array"}, + "filters": {"type": "object"}, + "brand_manifest": {"type": "object"}, + }, + "required": ["name"], + }, + }, + { + "name": "get_property_list", + "description": "Get a property list with optional resolution", + "inputSchema": { + "type": "object", + "properties": { + "list_id": {"type": "string"}, + "resolve": {"type": "boolean"}, + "pagination": {"type": "object"}, + }, + "required": ["list_id"], + }, + }, + { + "name": "list_property_lists", + "description": "List property lists", + "inputSchema": { + "type": "object", + "properties": { + "principal": {"type": "string"}, + "pagination": {"type": "object"}, + }, + }, + }, + { + "name": "update_property_list", + "description": "Update a property list", + "inputSchema": { + "type": "object", + "properties": { + "list_id": {"type": "string"}, + "name": {"type": "string"}, + "description": {"type": "string"}, + "filters": {"type": "object"}, + "brand_manifest": {"type": "object"}, + }, + "required": ["list_id"], + }, + }, + { + "name": "delete_property_list", + "description": "Delete a property list", + "inputSchema": { + "type": "object", + "properties": { + "list_id": {"type": "string"}, + }, + "required": ["list_id"], + }, + }, +] + + +def create_tool_caller( + handler: ADCPHandler, + method_name: str, +) -> Callable[[dict[str, Any]], Any]: + """Create a tool caller function for an ADCP handler method. + + Args: + handler: The ADCP handler instance + method_name: Name of the method to call + + Returns: + Async callable that invokes the handler method + """ + method = getattr(handler, method_name) + + async def call_tool(params: dict[str, Any]) -> Any: + context = ToolContext() + result = await method(params, context) + # Convert Pydantic models to dicts for MCP serialization + if hasattr(result, "model_dump"): + return result.model_dump(exclude_none=True) + return result + + return call_tool + + +class MCPToolSet: + """Collection of MCP tools from an ADCP handler. + + Provides tool definitions and handlers for registering with an MCP server. + """ + + def __init__(self, handler: ADCPHandler): + """Create tool set from handler. + + Args: + handler: ADCP handler instance + """ + self.handler = handler + self._tools: dict[str, Callable[[dict[str, Any]], Any]] = {} + + # Create tool callers for all methods + for tool_def in ADCP_TOOL_DEFINITIONS: + name = tool_def["name"] + self._tools[name] = create_tool_caller(handler, name) + + @property + def tool_definitions(self) -> list[dict[str, Any]]: + """Get MCP tool definitions.""" + return ADCP_TOOL_DEFINITIONS.copy() + + async def call_tool(self, name: str, params: dict[str, Any]) -> Any: + """Call a tool by name. + + Args: + name: Tool name + params: Tool parameters + + Returns: + Tool result + + Raises: + KeyError: If tool not found + """ + if name not in self._tools: + raise KeyError(f"Unknown tool: {name}") + return await self._tools[name](params) + + def get_tool_names(self) -> list[str]: + """Get list of available tool names.""" + return list(self._tools.keys()) + + +def create_mcp_tools(handler: ADCPHandler) -> MCPToolSet: + """Create MCP tools from an ADCP handler. + + This is the main entry point for MCP server integration. + + Example with mcp library: + from mcp.server import Server + from adcp.server import ContentStandardsHandler, create_mcp_tools + + class MyHandler(ContentStandardsHandler): + # ... implement methods + + handler = MyHandler() + tools = create_mcp_tools(handler) + + server = Server("my-content-agent") + + @server.list_tools() + async def list_tools(): + return tools.tool_definitions + + @server.call_tool() + async def call_tool(name: str, arguments: dict): + return await tools.call_tool(name, arguments) + + Args: + handler: ADCP handler instance + + Returns: + MCPToolSet with tool definitions and handlers + """ + return MCPToolSet(handler) diff --git a/src/adcp/server/proposal.py b/src/adcp/server/proposal.py new file mode 100644 index 00000000..7b2e7728 --- /dev/null +++ b/src/adcp/server/proposal.py @@ -0,0 +1,334 @@ +"""Proposal generation helpers. + +Provides utilities for building ADCP Proposals in get_products responses. +Proposals represent recommended media plans with budget allocations across products. +""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from typing import Any +from uuid import uuid4 + +from pydantic import BaseModel + +from adcp.types import Error + + +class ProposalNotSupported(BaseModel): + """Response indicating proposal generation is not supported. + + Use this when your agent supports get_products but not proposal generation. + """ + + proposals_supported: bool = False + reason: str = "This agent does not generate proposals" + error: Error | None = None + + +def proposals_not_supported( + reason: str = "This agent does not generate proposals", +) -> ProposalNotSupported: + """Create a response indicating proposals are not supported. + + Args: + reason: Human-readable explanation + + Returns: + ProposalNotSupported response + """ + return ProposalNotSupported( + proposals_supported=False, + reason=reason, + error=Error( + code="PROPOSALS_NOT_SUPPORTED", + message=reason, + ), + ) + + +class AllocationBuilder: + """Builder for product allocations within a proposal.""" + + def __init__( + self, + product_id: str, + allocation_percentage: float, + ): + """Create an allocation builder. + + Args: + product_id: ID of the product (must match a product in the response) + allocation_percentage: Percentage of budget (0-100) + """ + self._data: dict[str, Any] = { + "product_id": product_id, + "allocation_percentage": allocation_percentage, + } + + def with_pricing_option(self, pricing_option_id: str) -> AllocationBuilder: + """Specify which pricing option to use. + + Args: + pricing_option_id: ID from the product's pricing_options array + """ + self._data["pricing_option_id"] = pricing_option_id + return self + + def with_rationale(self, rationale: str) -> AllocationBuilder: + """Add explanation for this allocation. + + Args: + rationale: Why this product/allocation is recommended + """ + self._data["rationale"] = rationale + return self + + def with_sequence(self, sequence: int) -> AllocationBuilder: + """Set ordering hint for multi-line-item plans. + + Args: + sequence: 1-based ordering position + """ + self._data["sequence"] = sequence + return self + + def with_tags(self, tags: list[str]) -> AllocationBuilder: + """Add categorical tags. + + Args: + tags: Tags like 'desktop', 'mobile', 'german' + """ + self._data["tags"] = tags + return self + + def build(self) -> dict[str, Any]: + """Build the allocation dict.""" + return self._data.copy() + + +class ProposalBuilder: + """Builder for ADCP Proposals. + + Helps construct valid proposals for get_products responses. Proposals + represent recommended media plans with budget allocations. + + Example: + proposal = ( + ProposalBuilder("Q1 Brand Campaign") + .with_description("Balanced awareness campaign") + .add_allocation("product-1", 60) + .with_rationale("High-impact display") + .add_allocation("product-2", 40) + .with_rationale("Contextual targeting") + .with_budget_guidance(min=10000, recommended=25000, max=50000) + .build() + ) + """ + + def __init__(self, name: str, proposal_id: str | None = None): + """Create a new proposal builder. + + Args: + name: Human-readable name for the proposal + proposal_id: Unique ID (auto-generated if not provided) + """ + self._name = name + self._proposal_id = proposal_id or f"proposal-{uuid4().hex[:8]}" + self._description: str | None = None + self._brief_alignment: str | None = None + self._expires_at: datetime | None = None + self._allocations: list[dict[str, Any]] = [] + self._budget_guidance: dict[str, Any] | None = None + self._current_allocation: AllocationBuilder | None = None + self._ext: dict[str, Any] | None = None + + def with_description(self, description: str) -> ProposalBuilder: + """Add description explaining the proposal strategy. + + Args: + description: What the proposal achieves + """ + self._finalize_allocation() + self._description = description + return self + + def with_brief_alignment(self, alignment: str) -> ProposalBuilder: + """Explain how proposal aligns with campaign brief. + + Args: + alignment: Alignment explanation + """ + self._finalize_allocation() + self._brief_alignment = alignment + return self + + def expires_in(self, days: int = 7) -> ProposalBuilder: + """Set expiration relative to now. + + Args: + days: Number of days until expiration + """ + self._finalize_allocation() + self._expires_at = datetime.now(timezone.utc) + timedelta(days=days) + return self + + def expires_at(self, expires: datetime) -> ProposalBuilder: + """Set absolute expiration time. + + Args: + expires: When the proposal expires + """ + self._finalize_allocation() + self._expires_at = expires + return self + + def add_allocation( + self, + product_id: str, + allocation_percentage: float, + ) -> ProposalBuilder: + """Add a product allocation. + + After calling this, chain allocation methods (with_rationale, etc.) + before adding another allocation or calling build(). + + Args: + product_id: ID of the product + allocation_percentage: Percentage of budget (0-100) + + Returns: + Self for method chaining + """ + self._finalize_allocation() + self._current_allocation = AllocationBuilder(product_id, allocation_percentage) + return self + + def with_pricing_option(self, pricing_option_id: str) -> ProposalBuilder: + """Set pricing option for current allocation.""" + if self._current_allocation: + self._current_allocation.with_pricing_option(pricing_option_id) + return self + + def with_rationale(self, rationale: str) -> ProposalBuilder: + """Add rationale for current allocation.""" + if self._current_allocation: + self._current_allocation.with_rationale(rationale) + return self + + def with_sequence(self, sequence: int) -> ProposalBuilder: + """Set sequence for current allocation.""" + if self._current_allocation: + self._current_allocation.with_sequence(sequence) + return self + + def with_tags(self, tags: list[str]) -> ProposalBuilder: + """Add tags for current allocation.""" + if self._current_allocation: + self._current_allocation.with_tags(tags) + return self + + def with_budget_guidance( + self, + *, + min: float | None = None, + recommended: float | None = None, + max: float | None = None, + currency: str = "USD", + ) -> ProposalBuilder: + """Add budget guidance for the proposal. + + Args: + min: Minimum recommended budget + recommended: Optimal budget + max: Maximum before diminishing returns + currency: ISO 4217 currency code + """ + self._finalize_allocation() + self._budget_guidance = { + "currency": currency, + } + if min is not None: + self._budget_guidance["min"] = min + if recommended is not None: + self._budget_guidance["recommended"] = recommended + if max is not None: + self._budget_guidance["max"] = max + return self + + def with_extension(self, ext: dict[str, Any]) -> ProposalBuilder: + """Add extension data. + + Args: + ext: Extension object + """ + self._finalize_allocation() + self._ext = ext + return self + + def _finalize_allocation(self) -> None: + """Finalize current allocation and add to list.""" + if self._current_allocation: + self._allocations.append(self._current_allocation.build()) + self._current_allocation = None + + def build(self) -> dict[str, Any]: + """Build the proposal dict. + + Returns: + Proposal as a dict ready for use in get_products response + + Raises: + ValueError: If allocations don't sum to 100 + """ + self._finalize_allocation() + + if not self._allocations: + raise ValueError("Proposal must have at least one allocation") + + total = sum(a["allocation_percentage"] for a in self._allocations) + if abs(total - 100.0) > 0.01: + raise ValueError( + f"Allocation percentages must sum to 100, got {total}" + ) + + proposal: dict[str, Any] = { + "proposal_id": self._proposal_id, + "name": self._name, + "allocations": self._allocations, + } + + if self._description: + proposal["description"] = self._description + if self._brief_alignment: + proposal["brief_alignment"] = self._brief_alignment + if self._expires_at: + proposal["expires_at"] = self._expires_at.isoformat() + if self._budget_guidance: + proposal["total_budget_guidance"] = self._budget_guidance + if self._ext: + proposal["ext"] = self._ext + + return proposal + + def validate(self) -> list[str]: + """Validate the proposal without building. + + Returns: + List of validation errors (empty if valid) + """ + errors: list[str] = [] + + if self._current_allocation: + allocations = self._allocations + [self._current_allocation.build()] + else: + allocations = self._allocations + + if not allocations: + errors.append("Proposal must have at least one allocation") + else: + total = sum(a["allocation_percentage"] for a in allocations) + if abs(total - 100.0) > 0.01: + errors.append(f"Allocation percentages must sum to 100, got {total}") + + return errors diff --git a/src/adcp/server/sponsored_intelligence.py b/src/adcp/server/sponsored_intelligence.py new file mode 100644 index 00000000..1427d164 --- /dev/null +++ b/src/adcp/server/sponsored_intelligence.py @@ -0,0 +1,329 @@ +"""Sponsored Intelligence protocol handler. + +Provides a base class for implementing Sponsored Intelligence agents. +Non-SI operations return 'not supported' by default. +""" + +from __future__ import annotations + +from abc import abstractmethod +from typing import Any + +from adcp.server.base import ADCPHandler, NotImplementedResponse, ToolContext, not_supported +from adcp.types import ( + SiGetOfferingRequest, + SiGetOfferingResponse, + SiInitiateSessionRequest, + SiInitiateSessionResponse, + SiSendMessageRequest, + SiSendMessageResponse, + SiTerminateSessionRequest, + SiTerminateSessionResponse, +) + + +class SponsoredIntelligenceHandler(ADCPHandler): + """Handler for Sponsored Intelligence protocol. + + Subclass this to implement a Sponsored Intelligence agent. All SI + operations are abstract and must be implemented. Non-SI operations + (get_products, create_media_buy, content standards, etc.) return 'not supported'. + + Example: + class MySIHandler(SponsoredIntelligenceHandler): + async def si_get_offering( + self, + request: SiGetOfferingRequest, + context: ToolContext | None = None + ) -> SiGetOfferingResponse: + # Your implementation + return SiGetOfferingResponse(...) + """ + + # ======================================================================== + # Sponsored Intelligence Operations - MUST be implemented + # ======================================================================== + + @abstractmethod + async def si_get_offering( + self, + request: SiGetOfferingRequest, + context: ToolContext | None = None, + ) -> SiGetOfferingResponse: + """Get sponsored intelligence offering. + + Must be implemented by Sponsored Intelligence agents. + + Args: + request: SI offering request + context: Optional tool context + + Returns: + SI offering response with capabilities and pricing + """ + ... + + @abstractmethod + async def si_initiate_session( + self, + request: SiInitiateSessionRequest, + context: ToolContext | None = None, + ) -> SiInitiateSessionResponse: + """Initiate sponsored intelligence session. + + Must be implemented by Sponsored Intelligence agents. + + Args: + request: Session initiation request + context: Optional tool context + + Returns: + Session initiation response with session ID + """ + ... + + @abstractmethod + async def si_send_message( + self, + request: SiSendMessageRequest, + context: ToolContext | None = None, + ) -> SiSendMessageResponse: + """Send message in sponsored intelligence session. + + Must be implemented by Sponsored Intelligence agents. + + Args: + request: Message request with session ID and content + context: Optional tool context + + Returns: + Message response with AI-generated content + """ + ... + + @abstractmethod + async def si_terminate_session( + self, + request: SiTerminateSessionRequest, + context: ToolContext | None = None, + ) -> SiTerminateSessionResponse: + """Terminate sponsored intelligence session. + + Must be implemented by Sponsored Intelligence agents. + + Args: + request: Session termination request + context: Optional tool context + + Returns: + Termination response with session summary + """ + ... + + # ======================================================================== + # Non-SI Operations - Return 'not supported' + # ======================================================================== + + async def get_products( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "get_products is not supported by Sponsored Intelligence agents. " + "This agent handles conversational AI sponsorship, not product catalog operations." + ) + + async def list_creative_formats( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "list_creative_formats is not supported by Sponsored Intelligence agents." + ) + + async def list_authorized_properties( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "list_authorized_properties is not supported by Sponsored Intelligence agents." + ) + + async def sync_creatives( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "sync_creatives is not supported by Sponsored Intelligence agents." + ) + + async def list_creatives( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "list_creatives is not supported by Sponsored Intelligence agents." + ) + + async def build_creative( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "build_creative is not supported by Sponsored Intelligence agents." + ) + + async def create_media_buy( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "create_media_buy is not supported by Sponsored Intelligence agents. " + "SI sessions are initiated via si_initiate_session, not media buys." + ) + + async def update_media_buy( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "update_media_buy is not supported by Sponsored Intelligence agents." + ) + + async def get_media_buy_delivery( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "get_media_buy_delivery is not supported by Sponsored Intelligence agents." + ) + + async def get_signals( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "get_signals is not supported by Sponsored Intelligence agents." + ) + + async def activate_signal( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "activate_signal is not supported by Sponsored Intelligence agents." + ) + + async def provide_performance_feedback( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "provide_performance_feedback is not supported by Sponsored Intelligence agents." + ) + + # ======================================================================== + # V3 Content Standards - Not supported + # ======================================================================== + + async def create_content_standards( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "create_content_standards is not supported by Sponsored Intelligence agents. " + "Use a Content Standards agent for content calibration." + ) + + async def get_content_standards( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "get_content_standards is not supported by Sponsored Intelligence agents." + ) + + async def list_content_standards( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "list_content_standards is not supported by Sponsored Intelligence agents." + ) + + async def update_content_standards( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "update_content_standards is not supported by Sponsored Intelligence agents." + ) + + async def calibrate_content( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "calibrate_content is not supported by Sponsored Intelligence agents." + ) + + async def validate_content_delivery( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "validate_content_delivery is not supported by Sponsored Intelligence agents." + ) + + async def get_media_buy_artifacts( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "get_media_buy_artifacts is not supported by Sponsored Intelligence agents." + ) + + # ======================================================================== + # V3 Governance (Property Lists) - Not supported + # ======================================================================== + + async def create_property_list( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "create_property_list is not supported by Sponsored Intelligence agents. " + "Use a Governance agent for property list operations." + ) + + async def get_property_list( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "get_property_list is not supported by Sponsored Intelligence agents." + ) + + async def list_property_lists( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "list_property_lists is not supported by Sponsored Intelligence agents." + ) + + async def update_property_list( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "update_property_list is not supported by Sponsored Intelligence agents." + ) + + async def delete_property_list( + self, params: dict[str, Any], context: ToolContext | None = None + ) -> NotImplementedResponse: + """Not supported by Sponsored Intelligence agents.""" + return not_supported( + "delete_property_list is not supported by Sponsored Intelligence agents." + ) diff --git a/src/adcp/types/__init__.py b/src/adcp/types/__init__.py index 7f6f4b70..cbafe9b0 100644 --- a/src/adcp/types/__init__.py +++ b/src/adcp/types/__init__.py @@ -91,6 +91,7 @@ Embedding, Error, FeedbackSource, + FeedFormat, FieldModel, FlatRatePricingOption, Fonts, @@ -102,7 +103,10 @@ FormatIdParameter, FrequencyCap, FrequencyCapScope, - GeoCountryAnyOfItem, + GeoCountry, + GeoMetro, + GeoPostalArea, + GeoRegion, GetMediaBuyDeliveryRequest, GetMediaBuyDeliveryResponse, GetProductsRequest, @@ -136,7 +140,7 @@ Offering, Pacing, PackageRequest, - Packages, + PackageUpdate, Pagination, Parameters, Performance, @@ -175,7 +179,6 @@ ReportingPeriod, ReportingWebhook, Request, - RequestedMetric, Response, Responsive, Results, @@ -185,7 +188,7 @@ SignalFilters, Sort, SortApplied, - StandardFormatIds, + SortDirection, Status, StatusSummary, SyncCreativesRequest, @@ -214,6 +217,65 @@ from adcp.types._generated import TaskStatus as GeneratedTaskStatus from adcp.types._generated import _PackageFromPackage as Package +# V3 Protocol Discovery types +from adcp.types._generated import ( + GetAdcpCapabilitiesRequest, + GetAdcpCapabilitiesResponse, +) + +# V3 Content Standards types +from adcp.types._generated import ( + Artifact, + CalibrateContentRequest, + CalibrateContentResponse, + ContentStandards, + CreateContentStandardsRequest, + CreateContentStandardsResponse, + GetContentStandardsRequest, + GetContentStandardsResponse, + GetMediaBuyArtifactsRequest, + GetMediaBuyArtifactsResponse, + ListContentStandardsRequest, + ListContentStandardsResponse, + UpdateContentStandardsRequest, + UpdateContentStandardsResponse, + ValidateContentDeliveryRequest, + ValidateContentDeliveryResponse, +) + +# V3 Sponsored Intelligence types +from adcp.types._generated import ( + SiCapabilities, + SiGetOfferingRequest, + SiGetOfferingResponse, + SiIdentity, + SiInitiateSessionRequest, + SiInitiateSessionResponse, + SiSendMessageRequest, + SiSendMessageResponse, + SiTerminateSessionRequest, + SiTerminateSessionResponse, + SiUiElement, +) + +# V3 Governance (Property Lists) types +from adcp.types._generated import ( + CreatePropertyListRequest, + CreatePropertyListResponse, + DeletePropertyListRequest, + DeletePropertyListResponse, + GetPropertyListRequest, + GetPropertyListResponse, + ListPropertyListsRequest, + ListPropertyListsResponse, + PropertyList, + PropertyListChangedWebhook, + PropertyListFilters, + PropertyListReference, + UpdatePropertyListRequest, + UpdatePropertyListResponse, +) + # Import semantic aliases for discriminated unions from adcp.types.aliases import ( ActivateSignalErrorResponse, @@ -243,9 +305,7 @@ PreviewCreativeManifestRequest, PreviewCreativeStaticResponse, PropertyId, - PropertyIdActivationKey, PropertyTag, - PropertyTagActivationKey, ProvidePerformanceFeedbackErrorResponse, ProvidePerformanceFeedbackSuccessResponse, PublisherPropertiesAll, @@ -332,6 +392,53 @@ "Totals", "UpdateMediaBuyRequest", "UpdateMediaBuyResponse", + # V3 Protocol Discovery + "GetAdcpCapabilitiesRequest", + "GetAdcpCapabilitiesResponse", + # V3 Content Standards + "Artifact", + "CalibrateContentRequest", + "CalibrateContentResponse", + "ContentStandards", + "CreateContentStandardsRequest", + "CreateContentStandardsResponse", + "GetContentStandardsRequest", + "GetContentStandardsResponse", + "GetMediaBuyArtifactsRequest", + "GetMediaBuyArtifactsResponse", + "ListContentStandardsRequest", + "ListContentStandardsResponse", + "UpdateContentStandardsRequest", + "UpdateContentStandardsResponse", + "ValidateContentDeliveryRequest", + "ValidateContentDeliveryResponse", + # V3 Sponsored Intelligence + "SiCapabilities", + "SiGetOfferingRequest", + "SiGetOfferingResponse", + "SiIdentity", + "SiInitiateSessionRequest", + "SiInitiateSessionResponse", + "SiSendMessageRequest", + "SiSendMessageResponse", + "SiTerminateSessionRequest", + "SiTerminateSessionResponse", + "SiUiElement", + # V3 Governance (Property Lists) + "CreatePropertyListRequest", + "CreatePropertyListResponse", + "DeletePropertyListRequest", + "DeletePropertyListResponse", + "GetPropertyListRequest", + "GetPropertyListResponse", + "ListPropertyListsRequest", + "ListPropertyListsResponse", + "PropertyList", + "PropertyListChangedWebhook", + "PropertyListFilters", + "PropertyListReference", + "UpdatePropertyListRequest", + "UpdatePropertyListResponse", # Domain types "Asset", "AssetSelectors", @@ -375,7 +482,7 @@ "Offering", "Package", "PackageRequest", - "Packages", + "PackageUpdate", "Parameters", "Performance", "PerformanceFeedback", @@ -418,12 +525,15 @@ "DaastVersion", "DeliverTo", "DeliveryType", - "Direction", + "SortDirection", "FeedbackSource", "FieldModel", "FrequencyCap", "FrequencyCapScope", - "GeoCountryAnyOfItem", + "GeoCountry", + "GeoMetro", + "GeoPostalArea", + "GeoRegion", "MarkdownFlavor", "Measurement", "MeasurementPeriod", @@ -444,7 +554,6 @@ "WebhookResponseType", "Responsive", "Sort", - "StandardFormatIds", "Status", "TaskType", "DaastTrackingEvent", @@ -465,7 +574,6 @@ "ReportingFrequency", "ReportingPeriod", "ReportingWebhook", - "RequestedMetric", "AuthenticationScheme", "Security", # Assets @@ -513,9 +621,7 @@ "PreviewCreativeManifestRequest", "PreviewCreativeStaticResponse", "PropertyId", - "PropertyIdActivationKey", "PropertyTag", - "PropertyTagActivationKey", "ProvidePerformanceFeedbackErrorResponse", "ProvidePerformanceFeedbackSuccessResponse", "PublisherPropertiesAll", diff --git a/src/adcp/types/_ergonomic.py b/src/adcp/types/_ergonomic.py index 22a97d63..70a487f8 100644 --- a/src/adcp/types/_ergonomic.py +++ b/src/adcp/types/_ergonomic.py @@ -39,6 +39,7 @@ coerce_to_enum_list, coerce_to_model, ) + from adcp.types.generated_poc.core.context import ContextObject from adcp.types.generated_poc.core.creative_asset import CreativeAsset from adcp.types.generated_poc.core.creative_assignment import CreativeAssignment @@ -55,6 +56,20 @@ from adcp.types.generated_poc.media_buy.create_media_buy_request import ( CreateMediaBuyRequest, ) +from adcp.types.generated_poc.media_buy.get_products_request import GetProductsRequest +from adcp.types.generated_poc.media_buy.list_creative_formats_request import ( + ListCreativeFormatsRequest, +) +from adcp.types.generated_poc.media_buy.list_creatives_request import ( + FieldModel, + ListCreativesRequest, + Sort, +) +from adcp.types.generated_poc.media_buy.package_request import PackageRequest +from adcp.types.generated_poc.media_buy.package_update import ( + PackageUpdate1, + PackageUpdate2, +) from adcp.types.generated_poc.media_buy.create_media_buy_response import ( CreateMediaBuyResponse1, ) @@ -63,29 +78,15 @@ MediaBuyDelivery, NotificationType, ) -from adcp.types.generated_poc.media_buy.get_products_request import GetProductsRequest from adcp.types.generated_poc.media_buy.get_products_response import GetProductsResponse -from adcp.types.generated_poc.media_buy.list_creative_formats_request import ( - ListCreativeFormatsRequest, -) from adcp.types.generated_poc.media_buy.list_creative_formats_response import ( CreativeAgent, ListCreativeFormatsResponse, ) -from adcp.types.generated_poc.media_buy.list_creatives_request import ( - FieldModel, - ListCreativesRequest, - Sort, -) from adcp.types.generated_poc.media_buy.list_creatives_response import ( Creative, ListCreativesResponse, ) -from adcp.types.generated_poc.media_buy.package_request import PackageRequest -from adcp.types.generated_poc.media_buy.update_media_buy_request import ( - Packages, - Packages1, -) def _apply_coercion() -> None: @@ -179,9 +180,18 @@ def _apply_coercion() -> None: GetProductsRequest.model_rebuild(force=True) # Apply coercion to PackageRequest + # - creative_assignments: list[CreativeAssignment] (accepts subclass instances) # - creatives: list[CreativeAsset] (accepts subclass instances) # - ext: ExtensionObject | dict | None # - pacing: Pacing | str | None + _patch_field_annotation( + PackageRequest, + "creative_assignments", + Annotated[ + list[CreativeAssignment] | None, + BeforeValidator(coerce_subclass_list(CreativeAssignment)), + ], + ) _patch_field_annotation( PackageRequest, "creatives", @@ -220,18 +230,19 @@ def _apply_coercion() -> None: CreateMediaBuyRequest, "packages", Annotated[ - list[PackageRequest], + list[PackageRequest] | None, BeforeValidator(coerce_subclass_list(PackageRequest)), ], ) CreateMediaBuyRequest.model_rebuild(force=True) - # Apply coercion to Packages + # Apply coercion to PackageUpdate1 # - creative_assignments: list[CreativeAssignment] (accepts subclass instances) # - creatives: list[CreativeAsset] (accepts subclass instances) + # - ext: ExtensionObject | dict | None # - pacing: Pacing | str | None _patch_field_annotation( - Packages, + PackageUpdate1, "creative_assignments", Annotated[ list[CreativeAssignment] | None, @@ -239,7 +250,7 @@ def _apply_coercion() -> None: ], ) _patch_field_annotation( - Packages, + PackageUpdate1, "creatives", Annotated[ list[CreativeAsset] | None, @@ -247,18 +258,24 @@ def _apply_coercion() -> None: ], ) _patch_field_annotation( - Packages, + PackageUpdate1, + "ext", + Annotated[ExtensionObject | None, BeforeValidator(coerce_to_model(ExtensionObject))], + ) + _patch_field_annotation( + PackageUpdate1, "pacing", Annotated[Pacing | None, BeforeValidator(coerce_to_enum(Pacing))], ) - Packages.model_rebuild(force=True) + PackageUpdate1.model_rebuild(force=True) - # Apply coercion to Packages1 + # Apply coercion to PackageUpdate2 # - creative_assignments: list[CreativeAssignment] (accepts subclass instances) # - creatives: list[CreativeAsset] (accepts subclass instances) + # - ext: ExtensionObject | dict | None # - pacing: Pacing | str | None _patch_field_annotation( - Packages1, + PackageUpdate2, "creative_assignments", Annotated[ list[CreativeAssignment] | None, @@ -266,7 +283,7 @@ def _apply_coercion() -> None: ], ) _patch_field_annotation( - Packages1, + PackageUpdate2, "creatives", Annotated[ list[CreativeAsset] | None, @@ -274,11 +291,16 @@ def _apply_coercion() -> None: ], ) _patch_field_annotation( - Packages1, + PackageUpdate2, + "ext", + Annotated[ExtensionObject | None, BeforeValidator(coerce_to_model(ExtensionObject))], + ) + _patch_field_annotation( + PackageUpdate2, "pacing", Annotated[Pacing | None, BeforeValidator(coerce_to_enum(Pacing))], ) - Packages1.model_rebuild(force=True) + PackageUpdate2.model_rebuild(force=True) # Apply coercion to GetProductsResponse # - context: ContextObject | dict | None diff --git a/src/adcp/types/_generated.py b/src/adcp/types/_generated.py index b0e897ad..28417334 100644 --- a/src/adcp/types/_generated.py +++ b/src/adcp/types/_generated.py @@ -10,7 +10,7 @@ DO NOT EDIT MANUALLY. Generated from: https://github.com/adcontextprotocol/adcp/tree/main/schemas -Generation date: 2026-01-14 17:08:13 UTC +Generation date: 2026-01-25 21:17:54 UTC """ # ruff: noqa: E501, I001 @@ -29,6 +29,101 @@ PropertyFeature, Tags, ) +from adcp.types.generated_poc.content_standards.artifact import ( + Artifact, + AssetAccess, + AssetAccess1, + AssetAccess2, + AssetAccess3, + Assets, + Assets1, + Assets2, + Assets3, + Identifiers, + Metadata, + Provider, + Role, + TranscriptSource, + TranscriptSource1, +) +from adcp.types.generated_poc.content_standards.artifact_webhook_payload import ( + ArtifactWebhookPayload, + Pagination, +) +from adcp.types.generated_poc.content_standards.calibrate_content_request import ( + CalibrateContentRequest, +) +from adcp.types.generated_poc.content_standards.calibrate_content_response import ( + CalibrateContentResponse, + CalibrateContentResponse1, + CalibrateContentResponse2, + Feature, + Status, + Verdict, +) +from adcp.types.generated_poc.content_standards.content_standards import ( + CalibrationExemplars, + ContentStandards, +) +from adcp.types.generated_poc.content_standards.create_content_standards_request import ( + CreateContentStandardsRequest, + Fail, + Pass, + Scope, +) +from adcp.types.generated_poc.content_standards.create_content_standards_response import ( + CreateContentStandardsResponse, + CreateContentStandardsResponse1, + CreateContentStandardsResponse2, +) +from adcp.types.generated_poc.content_standards.get_content_standards_request import ( + GetContentStandardsRequest, +) +from adcp.types.generated_poc.content_standards.get_content_standards_response import ( + GetContentStandardsResponse, + GetContentStandardsResponse1, + GetContentStandardsResponse2, +) +from adcp.types.generated_poc.content_standards.get_media_buy_artifacts_request import ( + GetMediaBuyArtifactsRequest, + Method, + Sampling, + TimeRange, +) +from adcp.types.generated_poc.content_standards.get_media_buy_artifacts_response import ( + BrandContext, + GetMediaBuyArtifactsResponse, + GetMediaBuyArtifactsResponse1, + GetMediaBuyArtifactsResponse2, + LocalVerdict, + SamplingInfo, +) +from adcp.types.generated_poc.content_standards.list_content_standards_request import ( + ListContentStandardsRequest, +) +from adcp.types.generated_poc.content_standards.list_content_standards_response import ( + ListContentStandardsResponse, + ListContentStandardsResponse1, + ListContentStandardsResponse2, +) +from adcp.types.generated_poc.content_standards.update_content_standards_request import ( + UpdateContentStandardsRequest, +) +from adcp.types.generated_poc.content_standards.update_content_standards_response import ( + Error, + UpdateContentStandardsResponse, +) +from adcp.types.generated_poc.content_standards.validate_content_delivery_request import ( + Record, + ValidateContentDeliveryRequest, +) +from adcp.types.generated_poc.content_standards.validate_content_delivery_response import ( + Result, + Summary, + ValidateContentDeliveryResponse, + ValidateContentDeliveryResponse1, + ValidateContentDeliveryResponse2, +) from adcp.types.generated_poc.core.activation_key import ( ActivationKey, ActivationKey1, @@ -47,16 +142,18 @@ from adcp.types.generated_poc.core.assets.webhook_asset import Security, WebhookAsset from adcp.types.generated_poc.core.async_response_data import AdcpAsyncResponseData from adcp.types.generated_poc.core.brand_manifest import ( + AgenticCheckout, Asset, + Avatar, BrandManifest, Colors, Disclaimer, FeedFormat, Fonts, Logo, - Metadata, ProductCatalog, UpdateFrequency, + Voice, ) from adcp.types.generated_poc.core.brand_manifest_ref import BrandManifestReference from adcp.types.generated_poc.core.context import ContextObject @@ -73,12 +170,10 @@ ) from adcp.types.generated_poc.core.deployment import Deployment, Deployment1, Deployment2 from adcp.types.generated_poc.core.destination import Destination, Destination1, Destination2 -from adcp.types.generated_poc.core.error import Error from adcp.types.generated_poc.core.ext import ExtensionObject from adcp.types.generated_poc.core.format import ( Asset2, - Assets, - Assets1, + Assets5, AssetsRequired, AssetsRequired1, Dimensions, @@ -96,10 +191,11 @@ from adcp.types.generated_poc.core.mcp_webhook_payload import McpWebhookPayload from adcp.types.generated_poc.core.measurement import Measurement from adcp.types.generated_poc.core.media_buy import MediaBuy +from adcp.types.generated_poc.core.media_buy_features import MediaBuyFeatures +from adcp.types.generated_poc.core.offering import Offering from adcp.types.generated_poc.core.performance_feedback import ( MeasurementPeriod, PerformanceFeedback, - Status, ) from adcp.types.generated_poc.core.placement import Placement from adcp.types.generated_poc.core.pricing_option import PricingOption @@ -109,16 +205,19 @@ ProductCard, ProductCardDetailed, ) +from adcp.types.generated_poc.core.product_allocation import ProductAllocation from adcp.types.generated_poc.core.product_filters import ( BudgetRange, BudgetRange1, Country, + Metro, ProductFilters, + Region, + RequiredGeoTargetingItem, ) from adcp.types.generated_poc.core.promoted_offerings import ( AssetSelectors, AssetType, - Offering, PromotedOfferings, ) from adcp.types.generated_poc.core.promoted_products import PromotedProducts @@ -126,6 +225,7 @@ from adcp.types.generated_poc.core.property_id import PropertyId from adcp.types.generated_poc.core.property_list_ref import PropertyListReference from adcp.types.generated_poc.core.property_tag import PropertyTag +from adcp.types.generated_poc.core.proposal import Proposal, TotalBudgetGuidance from adcp.types.generated_poc.core.protocol_envelope import ProtocolEnvelope from adcp.types.generated_poc.core.publisher_property_selector import ( PublisherPropertySelector, @@ -138,11 +238,18 @@ PushNotificationConfig, ) from adcp.types.generated_poc.core.reporting_capabilities import ReportingCapabilities +from adcp.types.generated_poc.core.reporting_webhook import ReportingFrequency, ReportingWebhook from adcp.types.generated_poc.core.response import ProtocolResponse from adcp.types.generated_poc.core.signal_filters import SignalFilters from adcp.types.generated_poc.core.start_timing import StartTiming from adcp.types.generated_poc.core.sub_asset import SubAsset, SubAsset1, SubAsset2 -from adcp.types.generated_poc.core.targeting import GeoCountryAnyOfItem, TargetingOverlay +from adcp.types.generated_poc.core.targeting import ( + GeoCountry, + GeoMetro, + GeoPostalArea, + GeoRegion, + TargetingOverlay, +) from adcp.types.generated_poc.creative.list_creative_formats_request import ( ListCreativeFormatsRequestCreativeAgent, Type, @@ -182,7 +289,7 @@ from adcp.types.generated_poc.enums.asset_content_type import AssetContentType from adcp.types.generated_poc.enums.auth_scheme import AuthenticationScheme from adcp.types.generated_poc.enums.available_metric import AvailableMetric -from adcp.types.generated_poc.enums.channels import AdvertisingChannels +from adcp.types.generated_poc.enums.channels import MediaChannel from adcp.types.generated_poc.enums.co_branding_requirement import CoBrandingRequirement from adcp.types.generated_poc.enums.creative_action import CreativeAction from adcp.types.generated_poc.enums.creative_agent_capability import CreativeAgentCapability @@ -196,6 +303,7 @@ from adcp.types.generated_poc.enums.format_category import FormatCategory from adcp.types.generated_poc.enums.format_id_parameter import FormatIdParameter from adcp.types.generated_poc.enums.frequency_cap_scope import FrequencyCapScope +from adcp.types.generated_poc.enums.geo_level import GeographicTargetingLevel from adcp.types.generated_poc.enums.history_entry_type import HistoryEntryType from adcp.types.generated_poc.enums.http_method import HttpMethod from adcp.types.generated_poc.enums.identifier_types import PropertyIdentifierTypes @@ -204,16 +312,16 @@ from adcp.types.generated_poc.enums.markdown_flavor import MarkdownFlavor from adcp.types.generated_poc.enums.media_buy_status import MediaBuyStatus from adcp.types.generated_poc.enums.metric_type import MetricType +from adcp.types.generated_poc.enums.metro_system import MetroAreaSystem from adcp.types.generated_poc.enums.notification_type import NotificationType from adcp.types.generated_poc.enums.pacing import Pacing +from adcp.types.generated_poc.enums.postal_system import PostalCodeSystem from adcp.types.generated_poc.enums.preview_output_format import PreviewOutputFormat from adcp.types.generated_poc.enums.pricing_model import PricingModel from adcp.types.generated_poc.enums.property_type import PropertyType from adcp.types.generated_poc.enums.publisher_identifier_types import PublisherIdentifierTypes -from adcp.types.generated_poc.enums.reporting_frequency import ReportingFrequency from adcp.types.generated_poc.enums.signal_catalog_type import SignalCatalogType from adcp.types.generated_poc.enums.sort_direction import SortDirection -from adcp.types.generated_poc.enums.standard_format_ids import StandardFormatIds from adcp.types.generated_poc.enums.task_status import TaskStatus from adcp.types.generated_poc.enums.task_type import TaskType from adcp.types.generated_poc.enums.url_asset_type import UrlAssetType @@ -240,9 +348,11 @@ CreateMediaBuyWorking, ) from adcp.types.generated_poc.media_buy.create_media_buy_request import ( + ArtifactWebhook, + BatchFrequency, CreateMediaBuyRequest, - ReportingWebhook, - RequestedMetric, + DeliveryMode, + TotalBudget, ) from adcp.types.generated_poc.media_buy.create_media_buy_response import ( CreateMediaBuyResponse, @@ -290,7 +400,6 @@ from adcp.types.generated_poc.media_buy.list_creatives_request import ( FieldModel, ListCreativesRequest, - Pagination, Sort, ) from adcp.types.generated_poc.media_buy.list_creatives_response import ( @@ -304,6 +413,11 @@ StatusSummary, ) from adcp.types.generated_poc.media_buy.package_request import PackageRequest +from adcp.types.generated_poc.media_buy.package_update import ( + PackageUpdate, + PackageUpdate1, + PackageUpdate2, +) from adcp.types.generated_poc.media_buy.provide_performance_feedback_request import ( ProvidePerformanceFeedbackRequest, ProvidePerformanceFeedbackRequest1, @@ -339,10 +453,6 @@ UpdateMediaBuyWorking, ) from adcp.types.generated_poc.media_buy.update_media_buy_request import ( - Packages, - Packages1, - Packages2, - Packages3, UpdateMediaBuyRequest, UpdateMediaBuyRequest1, UpdateMediaBuyRequest2, @@ -385,12 +495,6 @@ from adcp.types.generated_poc.property.feature_requirement import FeatureRequirement, IfNotCovered from adcp.types.generated_poc.property.get_property_list_request import GetPropertyListRequest from adcp.types.generated_poc.property.get_property_list_response import GetPropertyListResponse -from adcp.types.generated_poc.property.list_property_features_request import ( - ListPropertyFeaturesRequest, -) -from adcp.types.generated_poc.property.list_property_features_response import ( - ListPropertyFeaturesResponse, -) from adcp.types.generated_poc.property.list_property_lists_request import ListPropertyListsRequest from adcp.types.generated_poc.property.list_property_lists_response import ListPropertyListsResponse from adcp.types.generated_poc.property.property_error import Code, PropertyError @@ -412,9 +516,32 @@ from adcp.types.generated_poc.property.update_property_list_response import ( UpdatePropertyListResponse, ) -from adcp.types.generated_poc.protocols.adcp_extension import ( - AdcpAgentCardExtensionParams, +from adcp.types.generated_poc.protocol.get_adcp_capabilities_request import ( + GetAdcpCapabilitiesRequest, + Protocol, +) +from adcp.types.generated_poc.protocol.get_adcp_capabilities_response import ( + Adcp, + CreativeSpecs, + Endpoint, + Execution, ExtensionsSupportedItem, + GeoMetros, + GeoPostalAreas, + GetAdcpCapabilitiesResponse, + Governance, + MajorVersion, + MraidVersion, + Portfolio, + Preferred, + Signals, + SponsoredIntelligence, + SupportedProtocol, + Targeting, + Transport, +) +from adcp.types.generated_poc.protocols.adcp_extension import ( + AdcpAgentCardExtensionParamsDeprecated, ProtocolsSupportedEnum, ) from adcp.types.generated_poc.signals.activate_signal_request import ActivateSignalRequest @@ -429,15 +556,69 @@ Pricing, Signal, ) +from adcp.types.generated_poc.sponsored_intelligence.si_capabilities import ( + Commerce, + Components, + Modalities, + SiCapabilities, + StandardEnum, + Video, +) +from adcp.types.generated_poc.sponsored_intelligence.si_get_offering_request import ( + SiGetOfferingRequest, +) +from adcp.types.generated_poc.sponsored_intelligence.si_get_offering_response import ( + MatchingProduct, + SiGetOfferingResponse, +) +from adcp.types.generated_poc.sponsored_intelligence.si_identity import ( + ConsentScopeEnum, + PrivacyPolicyAcknowledged, + ShippingAddress, + SiIdentity, + User, +) +from adcp.types.generated_poc.sponsored_intelligence.si_initiate_session_request import ( + SiInitiateSessionRequest, +) +from adcp.types.generated_poc.sponsored_intelligence.si_initiate_session_response import ( + SiInitiateSessionResponse, +) +from adcp.types.generated_poc.sponsored_intelligence.si_send_message_request import ( + ActionResponse, + SiSendMessageRequest, + SiSendMessageRequest1, + SiSendMessageRequest2, +) +from adcp.types.generated_poc.sponsored_intelligence.si_send_message_response import ( + ContextForCheckout, + Handoff, + Intent, + Price, + SessionStatus, + SiSendMessageResponse, +) +from adcp.types.generated_poc.sponsored_intelligence.si_terminate_session_request import ( + Action, + SiTerminateSessionRequest, + TerminationContext, + TransactionIntent, +) +from adcp.types.generated_poc.sponsored_intelligence.si_terminate_session_response import ( + AcpHandoff, + FollowUp, + SiTerminateSessionResponse, +) +from adcp.types.generated_poc.sponsored_intelligence.si_ui_element import SiUiElement # Special imports for name collisions (qualified names for types defined in multiple modules) from adcp.types.generated_poc.core.package import Package as _PackageFromPackage -# Backward compatibility aliases for renamed types -Channels = AdvertisingChannels - # Explicit exports __all__ = [ + "AcpHandoff", + "Action", + "ActionResponse", "ActivateSignalRequest", "ActivateSignalResponse", "ActivateSignalResponse1", @@ -445,19 +626,30 @@ "ActivationKey", "ActivationKey1", "ActivationKey2", - "AdcpAgentCardExtensionParams", + "Adcp", + "AdcpAgentCardExtensionParamsDeprecated", "AdcpAsyncResponseData", "AdcpDomain", "AdcpExtensionFileSchema", - "AdvertisingChannels", + "AgenticCheckout", "AggregatedTotals", + "Artifact", + "ArtifactWebhook", + "ArtifactWebhookPayload", "Asset", "Asset2", + "AssetAccess", + "AssetAccess1", + "AssetAccess2", + "AssetAccess3", "AssetContentType", "AssetSelectors", "AssetType", "Assets", "Assets1", + "Assets2", + "Assets3", + "Assets5", "AssetsRequired", "AssetsRequired1", "AssignedPackage", @@ -473,10 +665,13 @@ "AuthorizedSalesAgents1", "AuthorizedSalesAgents2", "AvailableMetric", + "Avatar", "BasePropertySource", "BasePropertySource1", "BasePropertySource2", "BasePropertySource3", + "BatchFrequency", + "BrandContext", "BrandManifest", "BrandManifestReference", "BudgetRange", @@ -486,12 +681,21 @@ "BuildCreativeResponse1", "BuildCreativeResponse2", "ByPackageItem", + "CalibrateContentRequest", + "CalibrateContentResponse", + "CalibrateContentResponse1", + "CalibrateContentResponse2", + "CalibrationExemplars", "ChangeSummary", - "Channels", "CoBrandingRequirement", "Code", "Colors", + "Commerce", + "Components", + "ConsentScopeEnum", "Contact", + "ContentStandards", + "ContextForCheckout", "ContextObject", "CountriesAllItem", "Country", @@ -502,6 +706,10 @@ "CpmFixedRatePricingOption", "CppPricingOption", "CpvPricingOption", + "CreateContentStandardsRequest", + "CreateContentStandardsResponse", + "CreateContentStandardsResponse1", + "CreateContentStandardsResponse2", "CreateMediaBuyInputRequired", "CreateMediaBuyRequest", "CreateMediaBuyResponse", @@ -521,6 +729,7 @@ "CreativeManifest", "CreativePolicy", "CreativeSortField", + "CreativeSpecs", "CreativeStatus", "CssAsset", "DaastAsset", @@ -534,6 +743,7 @@ "DeliverTo", "DeliveryMeasurement", "DeliveryMetrics", + "DeliveryMode", "DeliveryStatus", "DeliveryType", "Deployment", @@ -548,14 +758,19 @@ "Disclaimer", "DoohMetrics", "Embedding", + "Endpoint", "Error", + "Execution", "ExtensionObject", "ExtensionsSupportedItem", + "Fail", + "Feature", "FeatureRequirement", "FeedFormat", "FeedbackSource", "FieldModel", "FlatRatePricingOption", + "FollowUp", "Fonts", "Format", "FormatCard", @@ -565,7 +780,23 @@ "FormatIdParameter", "FrequencyCap", "FrequencyCapScope", - "GeoCountryAnyOfItem", + "GeoCountry", + "GeoMetro", + "GeoMetros", + "GeoPostalArea", + "GeoPostalAreas", + "GeoRegion", + "GeographicTargetingLevel", + "GetAdcpCapabilitiesRequest", + "GetAdcpCapabilitiesResponse", + "GetContentStandardsRequest", + "GetContentStandardsResponse", + "GetContentStandardsResponse1", + "GetContentStandardsResponse2", + "GetMediaBuyArtifactsRequest", + "GetMediaBuyArtifactsResponse", + "GetMediaBuyArtifactsResponse1", + "GetMediaBuyArtifactsResponse2", "GetMediaBuyDeliveryRequest", "GetMediaBuyDeliveryResponse", "GetProductsInputRequired", @@ -577,53 +808,72 @@ "GetPropertyListResponse", "GetSignalsRequest", "GetSignalsResponse", + "Governance", + "Handoff", "HistoryEntryType", "HtmlAsset", "HttpMethod", "Identifier", + "Identifiers", "IfNotCovered", "ImageAsset", "Input", "Input2", "Input4", + "Intent", "JavascriptAsset", "JavascriptModuleType", "LandingPageRequirement", "ListAuthorizedPropertiesRequest", "ListAuthorizedPropertiesResponse", + "ListContentStandardsRequest", + "ListContentStandardsResponse", + "ListContentStandardsResponse1", + "ListContentStandardsResponse2", "ListCreativeFormatsRequest", "ListCreativeFormatsRequestCreativeAgent", "ListCreativeFormatsResponse", "ListCreativeFormatsResponseCreativeAgent", "ListCreativesRequest", "ListCreativesResponse", - "ListPropertyFeaturesRequest", - "ListPropertyFeaturesResponse", "ListPropertyListsRequest", "ListPropertyListsResponse", + "LocalVerdict", "Logo", + "MajorVersion", "MarkdownFlavor", + "MatchingProduct", "McpWebhookPayload", "Measurement", "MeasurementPeriod", "MediaBuy", "MediaBuyDelivery", + "MediaBuyFeatures", "MediaBuyStatus", + "MediaChannel", "Metadata", + "Method", "MetricType", + "Metro", + "MetroAreaSystem", + "Modalities", + "MraidVersion", "NotificationType", "Offering", "Pacing", "PackageRequest", - "Packages", - "Packages1", - "Packages2", - "Packages3", + "PackageUpdate", + "PackageUpdate1", + "PackageUpdate2", "Pagination", "Parameters", + "Pass", "Performance", "PerformanceFeedback", "Placement", + "Portfolio", + "PostalCodeSystem", + "Preferred", "Preview", "Preview1", "Preview2", @@ -638,12 +888,15 @@ "PreviewRender1", "PreviewRender2", "PreviewRender3", + "Price", "PriceGuidance", "Pricing", "PricingModel", "PricingOption", "PrimaryCountry", + "PrivacyPolicyAcknowledged", "Product", + "ProductAllocation", "ProductCard", "ProductCardDetailed", "ProductCatalog", @@ -662,6 +915,8 @@ "PropertyListReference", "PropertyTag", "PropertyType", + "Proposal", + "Protocol", "ProtocolEnvelope", "ProtocolResponse", "ProtocolsSupportedEnum", @@ -671,6 +926,7 @@ "ProvidePerformanceFeedbackResponse", "ProvidePerformanceFeedbackResponse1", "ProvidePerformanceFeedbackResponse2", + "Provider", "PublisherDomain", "PublisherIdentifierTypes", "PublisherPropertySelector", @@ -682,6 +938,8 @@ "QuerySummary", "Range", "Reason", + "Record", + "Region", "Renders", "Renders1", "ReportingCapabilities", @@ -689,26 +947,50 @@ "ReportingPeriod", "ReportingWebhook", "Request", - "RequestedMetric", + "RequiredGeoTargetingItem", "Response", "Response1", "Responsive", + "Result", "Results", "Results1", + "Role", + "Sampling", + "SamplingInfo", + "Scope", "Security", + "SessionStatus", + "ShippingAddress", + "SiCapabilities", + "SiGetOfferingRequest", + "SiGetOfferingResponse", + "SiIdentity", + "SiInitiateSessionRequest", + "SiInitiateSessionResponse", + "SiSendMessageRequest", + "SiSendMessageRequest1", + "SiSendMessageRequest2", + "SiSendMessageResponse", + "SiTerminateSessionRequest", + "SiTerminateSessionResponse", + "SiUiElement", "Signal", "SignalCatalogType", "SignalFilters", + "Signals", "Sort", "SortApplied", "SortDirection", - "StandardFormatIds", + "SponsoredIntelligence", + "StandardEnum", "StartTiming", "Status", "StatusSummary", "SubAsset", "SubAsset1", "SubAsset2", + "Summary", + "SupportedProtocol", "SyncCreativesInputRequired", "SyncCreativesRequest", "SyncCreativesResponse", @@ -717,12 +999,23 @@ "SyncCreativesSubmitted", "SyncCreativesWorking", "Tags", + "Targeting", "TargetingOverlay", "TaskStatus", "TaskType", + "TerminationContext", "TextAsset", + "TimeRange", + "TotalBudget", + "TotalBudgetGuidance", "Totals", + "TransactionIntent", + "TranscriptSource", + "TranscriptSource1", + "Transport", "Type", + "UpdateContentStandardsRequest", + "UpdateContentStandardsResponse", "UpdateFrequency", "UpdateMediaBuyInputRequired", "UpdateMediaBuyRequest", @@ -737,6 +1030,11 @@ "UpdatePropertyListResponse", "UrlAsset", "UrlAssetType", + "User", + "ValidateContentDeliveryRequest", + "ValidateContentDeliveryResponse", + "ValidateContentDeliveryResponse1", + "ValidateContentDeliveryResponse2", "ValidationMode", "VastAsset", "VastAsset1", @@ -746,9 +1044,12 @@ "VcpmAuctionPricingOption", "VcpmFixedRatePricingOption", "VenueBreakdownItem", + "Verdict", + "Video", "VideoAsset", "ViewThreshold", "ViewThreshold1", + "Voice", "WebhookAsset", "WebhookResponseType", "WebhookSecurityMethod", diff --git a/src/adcp/types/aliases.py b/src/adcp/types/aliases.py index fd1220b2..e28b5b31 100644 --- a/src/adcp/types/aliases.py +++ b/src/adcp/types/aliases.py @@ -35,9 +35,6 @@ # Activation responses ActivateSignalResponse1, ActivateSignalResponse2, - # Activation keys - ActivationKey1, - ActivationKey2, # Authorized agents AuthorizedAgents, AuthorizedAgents1, @@ -198,12 +195,11 @@ def process_result(result: SyncCreativeResult) -> None: # ============================================================================ # ACTIVATION KEY ALIASES # ============================================================================ - -PropertyIdActivationKey = ActivationKey1 -"""Activation key using property_id for identification.""" - -PropertyTagActivationKey = ActivationKey2 -"""Activation key using property_tags for identification.""" +# Note: Activation key schema changed from property_id/property_tag variants +# to segment_id/key_value variants. Import directly from _generated: +# from adcp.types._generated import ActivationKey1 as SegmentIdActivationKey +# from adcp.types._generated import ActivationKey2 as KeyValueActivationKey +# These will be added once the types are regenerated with proper schema. # ============================================================================ # PREVIEW/RENDER TYPE ALIASES @@ -700,9 +696,6 @@ def filter_products(props: PublisherProperties) -> None: # Activation responses "ActivateSignalSuccessResponse", "ActivateSignalErrorResponse", - # Activation keys - "PropertyIdActivationKey", - "PropertyTagActivationKey", # Asset type aliases "BothPreviewRender", "HtmlPreviewRender", diff --git a/src/adcp/types/generated_poc/adagents.py b/src/adcp/types/generated_poc/adagents.py index 21dc5abf..8b5fa9a0 100644 --- a/src/adcp/types/generated_poc/adagents.py +++ b/src/adcp/types/generated_poc/adagents.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: adagents.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,39 +14,39 @@ class AuthorizedSalesAgents1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) field_schema: Annotated[ str | None, - Field(alias="$schema", description="JSON Schema identifier for this adagents.json file"), + Field(alias='$schema', description='JSON Schema identifier for this adagents.json file'), ] = None authoritative_location: Annotated[ AnyUrl, Field( - description="HTTPS URL of the authoritative adagents.json file. When present, this file is a reference and the authoritative location contains the actual agent authorization data." + description='HTTPS URL of the authoritative adagents.json file. When present, this file is a reference and the authoritative location contains the actual agent authorization data.' ), ] last_updated: Annotated[ AwareDatetime | None, - Field(description="ISO 8601 timestamp indicating when this reference was last updated"), + Field(description='ISO 8601 timestamp indicating when this reference was last updated'), ] = None class Contact(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) domain: Annotated[ str | None, Field( - description="Primary domain of the entity managing this file", - pattern="^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$", + description='Primary domain of the entity managing this file', + pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$', ), ] = None email: Annotated[ EmailStr | None, Field( - description="Contact email for questions or issues with this authorization file", + description='Contact email for questions or issues with this authorization file', max_length=255, min_length=1, ), @@ -59,10 +59,16 @@ class Contact(AdCPBaseModel): min_length=1, ), ] + privacy_policy_url: Annotated[ + AnyUrl | None, + Field( + description="URL to the entity's privacy policy. Used for consumer consent flows when interacting with this sales agent." + ), + ] = None seller_id: Annotated[ str | None, Field( - description="Seller ID from IAB Tech Lab sellers.json (if applicable)", + description='Seller ID from IAB Tech Lab sellers.json (if applicable)', max_length=255, min_length=1, ), @@ -70,7 +76,7 @@ class Contact(AdCPBaseModel): tag_id: Annotated[ str | None, Field( - description="TAG Certified Against Fraud ID for verification (if applicable)", + description='TAG Certified Against Fraud ID for verification (if applicable)', max_length=100, min_length=1, ), @@ -79,7 +85,7 @@ class Contact(AdCPBaseModel): class PropertyFeature(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) features: Annotated[ list[str], @@ -95,7 +101,7 @@ class PropertyFeature(AdCPBaseModel): ), ] publisher_id: Annotated[ - str | None, Field(description="Optional publisher identifier at this agent (for lookup)") + str | None, Field(description='Optional publisher identifier at this agent (for lookup)') ] = None url: Annotated[ AnyUrl, @@ -105,24 +111,24 @@ class PropertyFeature(AdCPBaseModel): class Tags(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - description: Annotated[str, Field(description="Description of what this tag represents")] - name: Annotated[str, Field(description="Human-readable name for this tag")] + description: Annotated[str, Field(description='Description of what this tag represents')] + name: Annotated[str, Field(description='Human-readable name for this tag')] class AuthorizedAgents(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) authorization_type: Annotated[ - Literal["property_ids"], - Field(description="Discriminator indicating authorization by specific property IDs"), + Literal['property_ids'], + Field(description='Discriminator indicating authorization by specific property IDs'), ] authorized_for: Annotated[ str, Field( - description="Human-readable description of what this agent is authorized to sell", + description='Human-readable description of what this agent is authorized to sell', max_length=500, min_length=1, ), @@ -130,7 +136,7 @@ class AuthorizedAgents(AdCPBaseModel): property_ids: Annotated[ list[property_id.PropertyId], Field( - description="Property IDs this agent is authorized for. Resolved against the top-level properties array in this file", + description='Property IDs this agent is authorized for. Resolved against the top-level properties array in this file', min_length=1, ), ] @@ -139,16 +145,16 @@ class AuthorizedAgents(AdCPBaseModel): class AuthorizedAgents1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) authorization_type: Annotated[ - Literal["property_tags"], - Field(description="Discriminator indicating authorization by property tags"), + Literal['property_tags'], + Field(description='Discriminator indicating authorization by property tags'), ] authorized_for: Annotated[ str, Field( - description="Human-readable description of what this agent is authorized to sell", + description='Human-readable description of what this agent is authorized to sell', max_length=500, min_length=1, ), @@ -156,7 +162,7 @@ class AuthorizedAgents1(AdCPBaseModel): property_tags: Annotated[ list[property_tag.PropertyTag], Field( - description="Tags identifying which properties this agent is authorized for. Resolved against the top-level properties array in this file using tag matching", + description='Tags identifying which properties this agent is authorized for. Resolved against the top-level properties array in this file using tag matching', min_length=1, ), ] @@ -165,18 +171,18 @@ class AuthorizedAgents1(AdCPBaseModel): class AuthorizedAgents3(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) authorization_type: Annotated[ - Literal["publisher_properties"], + Literal['publisher_properties'], Field( - description="Discriminator indicating authorization for properties from other publisher domains" + description='Discriminator indicating authorization for properties from other publisher domains' ), ] authorized_for: Annotated[ str, Field( - description="Human-readable description of what this agent is authorized to sell", + description='Human-readable description of what this agent is authorized to sell', max_length=500, min_length=1, ), @@ -184,7 +190,7 @@ class AuthorizedAgents3(AdCPBaseModel): publisher_properties: Annotated[ list[publisher_property_selector.PublisherPropertySelector], Field( - description="Properties from other publisher domains this agent is authorized for. Each entry specifies a publisher domain and which of their properties this agent can sell", + description='Properties from other publisher domains this agent is authorized for. Each entry specifies a publisher domain and which of their properties this agent can sell', min_length=1, ), ] @@ -193,16 +199,16 @@ class AuthorizedAgents3(AdCPBaseModel): class AuthorizedAgents2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) authorization_type: Annotated[ - Literal["inline_properties"], - Field(description="Discriminator indicating authorization by inline property definitions"), + Literal['inline_properties'], + Field(description='Discriminator indicating authorization by inline property definitions'), ] authorized_for: Annotated[ str, Field( - description="Human-readable description of what this agent is authorized to sell", + description='Human-readable description of what this agent is authorized to sell', max_length=500, min_length=1, ), @@ -210,7 +216,7 @@ class AuthorizedAgents2(AdCPBaseModel): properties: Annotated[ list[property.Property], Field( - description="Specific properties this agent is authorized for (alternative to property_ids/property_tags)", + description='Specific properties this agent is authorized for (alternative to property_ids/property_tags)', min_length=1, ), ] @@ -219,33 +225,33 @@ class AuthorizedAgents2(AdCPBaseModel): class AuthorizedSalesAgents2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) field_schema: Annotated[ str | None, - Field(alias="$schema", description="JSON Schema identifier for this adagents.json file"), + Field(alias='$schema', description='JSON Schema identifier for this adagents.json file'), ] = None authorized_agents: Annotated[ list[AuthorizedAgents | AuthorizedAgents1 | AuthorizedAgents2 | AuthorizedAgents3], Field( - description="Array of sales agents authorized to sell inventory for properties in this file", + description='Array of sales agents authorized to sell inventory for properties in this file', min_length=1, ), ] contact: Annotated[ Contact | None, Field( - description="Contact information for the entity managing this adagents.json file (may be publisher or third-party operator)" + description='Contact information for the entity managing this adagents.json file (may be publisher or third-party operator)' ), ] = None last_updated: Annotated[ AwareDatetime | None, - Field(description="ISO 8601 timestamp indicating when this file was last updated"), + Field(description='ISO 8601 timestamp indicating when this file was last updated'), ] = None properties: Annotated[ list[property.Property] | None, Field( - description="Array of all properties covered by this adagents.json file. Defines the canonical property list that authorized agents reference.", + description='Array of all properties covered by this adagents.json file. Defines the canonical property list that authorized agents reference.', min_length=1, ), ] = None @@ -258,7 +264,7 @@ class AuthorizedSalesAgents2(AdCPBaseModel): tags: Annotated[ dict[str, Tags] | None, Field( - description="Metadata for each tag referenced by properties. Provides human-readable context for property tag values." + description='Metadata for each tag referenced by properties. Provides human-readable context for property tag values.' ), ] = None @@ -267,231 +273,232 @@ class AuthorizedSalesAgents(RootModel[AuthorizedSalesAgents1 | AuthorizedSalesAg root: Annotated[ AuthorizedSalesAgents1 | AuthorizedSalesAgents2, Field( - description="Declaration of authorized sales agents for advertising inventory. Hosted at /.well-known/adagents.json on publisher domains. Can either contain the full structure inline or reference an authoritative URL.", + description='Declaration of authorized sales agents for advertising inventory. Hosted at /.well-known/adagents.json on publisher domains. Can either contain the full structure inline or reference an authoritative URL.', examples=[ { - "$schema": "/schemas/2.6.0/adagents.json", - "authoritative_location": "https://cdn.example.com/adagents/v2/adagents.json", - "last_updated": "2025-01-15T10:00:00Z", + '$schema': '/schemas/latest/adagents.json', + 'authoritative_location': 'https://cdn.example.com/adagents/v2/adagents.json', + 'last_updated': '2025-01-15T10:00:00Z', }, { - "$schema": "/schemas/2.6.0/adagents.json", - "authorized_agents": [ + '$schema': '/schemas/latest/adagents.json', + 'authorized_agents': [ { - "authorization_type": "property_tags", - "authorized_for": "Official sales agent", - "property_tags": ["all"], - "url": "https://agent.example.com", + 'authorization_type': 'property_tags', + 'authorized_for': 'Official sales agent', + 'property_tags': ['all'], + 'url': 'https://agent.example.com', } ], - "last_updated": "2025-01-10T12:00:00Z", - "properties": [ + 'last_updated': '2025-01-10T12:00:00Z', + 'properties': [ { - "identifiers": [{"type": "domain", "value": "example.com"}], - "name": "Example Site", - "property_type": "website", - "publisher_domain": "example.com", + 'identifiers': [{'type': 'domain', 'value': 'example.com'}], + 'name': 'Example Site', + 'property_type': 'website', + 'publisher_domain': 'example.com', } ], - "tags": { - "all": { - "description": "All properties in this file", - "name": "All Properties", + 'tags': { + 'all': { + 'description': 'All properties in this file', + 'name': 'All Properties', } }, }, { - "$schema": "/schemas/2.6.0/adagents.json", - "authorized_agents": [ + '$schema': '/schemas/latest/adagents.json', + 'authorized_agents': [ { - "authorization_type": "property_tags", - "authorized_for": "All Meta properties", - "property_tags": ["meta_network"], - "url": "https://meta-ads.com", + 'authorization_type': 'property_tags', + 'authorized_for': 'All Meta properties', + 'property_tags': ['meta_network'], + 'url': 'https://meta-ads.com', } ], - "contact": { - "domain": "meta.com", - "email": "adops@meta.com", - "name": "Meta Advertising Operations", - "seller_id": "pub-meta-12345", - "tag_id": "12345", + 'contact': { + 'domain': 'meta.com', + 'email': 'adops@meta.com', + 'name': 'Meta Advertising Operations', + 'privacy_policy_url': 'https://www.meta.com/privacy/policy', + 'seller_id': 'pub-meta-12345', + 'tag_id': '12345', }, - "last_updated": "2025-01-10T15:30:00Z", - "properties": [ + 'last_updated': '2025-01-10T15:30:00Z', + 'properties': [ { - "identifiers": [ - {"type": "ios_bundle", "value": "com.burbn.instagram"}, - {"type": "android_package", "value": "com.instagram.android"}, + 'identifiers': [ + {'type': 'ios_bundle', 'value': 'com.burbn.instagram'}, + {'type': 'android_package', 'value': 'com.instagram.android'}, ], - "name": "Instagram", - "property_type": "mobile_app", - "publisher_domain": "instagram.com", - "tags": ["meta_network", "social_media"], + 'name': 'Instagram', + 'property_type': 'mobile_app', + 'publisher_domain': 'instagram.com', + 'tags': ['meta_network', 'social_media'], }, { - "identifiers": [ - {"type": "ios_bundle", "value": "com.facebook.Facebook"}, - {"type": "android_package", "value": "com.facebook.katana"}, + 'identifiers': [ + {'type': 'ios_bundle', 'value': 'com.facebook.Facebook'}, + {'type': 'android_package', 'value': 'com.facebook.katana'}, ], - "name": "Facebook", - "property_type": "mobile_app", - "publisher_domain": "facebook.com", - "tags": ["meta_network", "social_media"], + 'name': 'Facebook', + 'property_type': 'mobile_app', + 'publisher_domain': 'facebook.com', + 'tags': ['meta_network', 'social_media'], }, { - "identifiers": [ - {"type": "ios_bundle", "value": "net.whatsapp.WhatsApp"}, - {"type": "android_package", "value": "com.whatsapp"}, + 'identifiers': [ + {'type': 'ios_bundle', 'value': 'net.whatsapp.WhatsApp'}, + {'type': 'android_package', 'value': 'com.whatsapp'}, ], - "name": "WhatsApp", - "property_type": "mobile_app", - "publisher_domain": "whatsapp.com", - "tags": ["meta_network", "messaging"], + 'name': 'WhatsApp', + 'property_type': 'mobile_app', + 'publisher_domain': 'whatsapp.com', + 'tags': ['meta_network', 'messaging'], }, ], - "tags": { - "messaging": { - "description": "Messaging and communication apps", - "name": "Messaging Apps", + 'tags': { + 'messaging': { + 'description': 'Messaging and communication apps', + 'name': 'Messaging Apps', }, - "meta_network": { - "description": "All Meta-owned properties", - "name": "Meta Network", + 'meta_network': { + 'description': 'All Meta-owned properties', + 'name': 'Meta Network', }, - "social_media": { - "description": "Social networking applications", - "name": "Social Media Apps", + 'social_media': { + 'description': 'Social networking applications', + 'name': 'Social Media Apps', }, }, }, { - "$schema": "/schemas/2.6.0/adagents.json", - "authorized_agents": [ + '$schema': '/schemas/latest/adagents.json', + 'authorized_agents': [ { - "authorization_type": "property_tags", - "authorized_for": "Tumblr corporate properties only", - "property_tags": ["corporate"], - "url": "https://tumblr-sales.com", + 'authorization_type': 'property_tags', + 'authorized_for': 'Tumblr corporate properties only', + 'property_tags': ['corporate'], + 'url': 'https://tumblr-sales.com', } ], - "contact": {"name": "Tumblr Advertising"}, - "last_updated": "2025-01-10T16:00:00Z", - "properties": [ + 'contact': {'name': 'Tumblr Advertising'}, + 'last_updated': '2025-01-10T16:00:00Z', + 'properties': [ { - "identifiers": [{"type": "domain", "value": "tumblr.com"}], - "name": "Tumblr Corporate", - "property_type": "website", - "publisher_domain": "tumblr.com", - "tags": ["corporate"], + 'identifiers': [{'type': 'domain', 'value': 'tumblr.com'}], + 'name': 'Tumblr Corporate', + 'property_type': 'website', + 'publisher_domain': 'tumblr.com', + 'tags': ['corporate'], } ], - "tags": { - "corporate": { - "description": "Tumblr-owned corporate properties (not user blogs)", - "name": "Corporate Properties", + 'tags': { + 'corporate': { + 'description': 'Tumblr-owned corporate properties (not user blogs)', + 'name': 'Corporate Properties', } }, }, { - "$schema": "/schemas/2.6.0/adagents.json", - "authorized_agents": [ + '$schema': '/schemas/latest/adagents.json', + 'authorized_agents': [ { - "authorization_type": "publisher_properties", - "authorized_for": "CNN CTV properties via publisher authorization", - "publisher_properties": [ + 'authorization_type': 'publisher_properties', + 'authorized_for': 'CNN CTV properties via publisher authorization', + 'publisher_properties': [ { - "property_ids": ["cnn_ctv_app"], - "publisher_domain": "cnn.com", - "selection_type": "by_id", + 'property_ids': ['cnn_ctv_app'], + 'publisher_domain': 'cnn.com', + 'selection_type': 'by_id', } ], - "url": "https://agent.example/api", + 'url': 'https://agent.example/api', }, { - "authorization_type": "publisher_properties", - "authorized_for": "All CTV properties from multiple publishers", - "publisher_properties": [ + 'authorization_type': 'publisher_properties', + 'authorized_for': 'All CTV properties from multiple publishers', + 'publisher_properties': [ { - "property_tags": ["ctv"], - "publisher_domain": "cnn.com", - "selection_type": "by_tag", + 'property_tags': ['ctv'], + 'publisher_domain': 'cnn.com', + 'selection_type': 'by_tag', }, { - "property_tags": ["ctv"], - "publisher_domain": "espn.com", - "selection_type": "by_tag", + 'property_tags': ['ctv'], + 'publisher_domain': 'espn.com', + 'selection_type': 'by_tag', }, ], - "url": "https://agent.example/api", + 'url': 'https://agent.example/api', }, ], - "contact": { - "domain": "agent.example", - "email": "sales@agent.example", - "name": "Example Third-Party Sales Agent", + 'contact': { + 'domain': 'agent.example', + 'email': 'sales@agent.example', + 'name': 'Example Third-Party Sales Agent', }, - "last_updated": "2025-01-10T17:00:00Z", + 'last_updated': '2025-01-10T17:00:00Z', }, { - "$schema": "/schemas/2.6.0/adagents.json", - "authorized_agents": [ + '$schema': '/schemas/latest/adagents.json', + 'authorized_agents': [ { - "authorization_type": "property_tags", - "authorized_for": "All news properties", - "property_tags": ["news"], - "url": "https://sales.news.example.com", + 'authorization_type': 'property_tags', + 'authorized_for': 'All news properties', + 'property_tags': ['news'], + 'url': 'https://sales.news.example.com', } ], - "contact": { - "domain": "news.example.com", - "email": "adops@news.example.com", - "name": "Premium News Publisher", + 'contact': { + 'domain': 'news.example.com', + 'email': 'adops@news.example.com', + 'name': 'Premium News Publisher', }, - "last_updated": "2025-01-10T18:00:00Z", - "properties": [ + 'last_updated': '2025-01-10T18:00:00Z', + 'properties': [ { - "identifiers": [{"type": "domain", "value": "news.example.com"}], - "name": "News Example", - "property_type": "website", - "publisher_domain": "news.example.com", - "tags": ["premium", "news"], + 'identifiers': [{'type': 'domain', 'value': 'news.example.com'}], + 'name': 'News Example', + 'property_type': 'website', + 'publisher_domain': 'news.example.com', + 'tags': ['premium', 'news'], } ], - "property_features": [ + 'property_features': [ { - "features": ["carbon_score", "sustainability_grade"], - "name": "Scope3", - "publisher_id": "pub_news_12345", - "url": "https://api.scope3.com", + 'features': ['carbon_score', 'sustainability_grade'], + 'name': 'Scope3', + 'publisher_id': 'pub_news_12345', + 'url': 'https://api.scope3.com', }, { - "features": [ - "tag_certified_against_fraud", - "tag_brand_safety_certified", + 'features': [ + 'tag_certified_against_fraud', + 'tag_brand_safety_certified', ], - "name": "TAG", - "url": "https://api.tagtoday.net", + 'name': 'TAG', + 'url': 'https://api.tagtoday.net', }, { - "features": ["gdpr_compliant", "tcf_registered", "ccpa_compliant"], - "name": "OneTrust", - "publisher_id": "ot_news_67890", - "url": "https://api.onetrust.com", + 'features': ['gdpr_compliant', 'tcf_registered', 'ccpa_compliant'], + 'name': 'OneTrust', + 'publisher_id': 'ot_news_67890', + 'url': 'https://api.onetrust.com', }, ], - "tags": { - "news": { - "description": "News and journalism content", - "name": "News Properties", + 'tags': { + 'news': { + 'description': 'News and journalism content', + 'name': 'News Properties', }, - "premium": { - "description": "High-quality, brand-safe properties", - "name": "Premium Properties", + 'premium': { + 'description': 'High-quality, brand-safe properties', + 'name': 'Premium Properties', }, }, }, ], - title="Authorized Sales Agents", + title='Authorized Sales Agents', ), ] diff --git a/src/adcp/types/generated_poc/content_standards/__init__.py b/src/adcp/types/generated_poc/content_standards/__init__.py new file mode 100644 index 00000000..93575326 --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/__init__.py @@ -0,0 +1,3 @@ +# generated by datamodel-codegen: +# filename: .schema_temp +# timestamp: 2026-01-25T21:17:54+00:00 diff --git a/src/adcp/types/generated_poc/content_standards/artifact.py b/src/adcp/types/generated_poc/content_standards/artifact.py new file mode 100644 index 00000000..861bafd3 --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/artifact.py @@ -0,0 +1,208 @@ +# generated by datamodel-codegen: +# filename: content_standards/artifact.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated, Any, Literal + +from adcp.types.base import AdCPBaseModel +from pydantic import AnyUrl, AwareDatetime, ConfigDict, Field, RootModel + +from ..core import format_id as format_id_1 +from ..core import identifier + + +class Role(Enum): + title_ = 'title' + paragraph = 'paragraph' + heading = 'heading' + caption = 'caption' + quote = 'quote' + list_item = 'list_item' + description = 'description' + + +class Assets(AdCPBaseModel): + content: Annotated[str, Field(description='Text content')] + heading_level: Annotated[ + int | None, Field(description='Heading level (1-6), only for role=heading', ge=1, le=6) + ] = None + language: Annotated[ + str | None, + Field( + description="BCP 47 language tag for this text (e.g., 'en', 'es-MX'). Useful when artifact contains mixed-language content." + ), + ] = None + role: Annotated[ + Role | None, + Field( + description="Role of this text in the document. Use 'title' for the main artifact title, 'description' for summaries." + ), + ] = None + type: Literal['text'] + + +class TranscriptSource(Enum): + original_script = 'original_script' + subtitles = 'subtitles' + closed_captions = 'closed_captions' + dub = 'dub' + generated = 'generated' + + +class TranscriptSource1(Enum): + original_script = 'original_script' + closed_captions = 'closed_captions' + generated = 'generated' + + +class Identifiers(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + apple_podcast_id: Annotated[str | None, Field(description='Apple Podcasts ID')] = None + podcast_guid: Annotated[str | None, Field(description='Podcast GUID (from RSS feed)')] = None + rss_url: Annotated[AnyUrl | None, Field(description='RSS feed URL')] = None + spotify_show_id: Annotated[str | None, Field(description='Spotify show ID')] = None + youtube_video_id: Annotated[str | None, Field(description='YouTube video ID')] = None + + +class Metadata(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + author: Annotated[str | None, Field(description='Artifact author name')] = None + canonical: Annotated[AnyUrl | None, Field(description='Canonical URL')] = None + json_ld: Annotated[ + list[dict[str, Any]] | None, Field(description='JSON-LD structured data (schema.org)') + ] = None + keywords: Annotated[str | None, Field(description='Artifact keywords')] = None + open_graph: Annotated[ + dict[str, Any] | None, Field(description='Open Graph protocol metadata') + ] = None + twitter_card: Annotated[dict[str, Any] | None, Field(description='Twitter Card metadata')] = ( + None + ) + + +class AssetAccess1(AdCPBaseModel): + method: Literal['bearer_token'] + token: Annotated[str, Field(description='OAuth2 bearer token for Authorization header')] + + +class Provider(Enum): + gcp = 'gcp' + aws = 'aws' + + +class AssetAccess2(AdCPBaseModel): + credentials: Annotated[ + dict[str, Any] | None, Field(description='Service account credentials') + ] = None + method: Literal['service_account'] + provider: Annotated[Provider, Field(description='Cloud provider')] + + +class AssetAccess3(AdCPBaseModel): + method: Literal['signed_url'] + + +class AssetAccess(RootModel[AssetAccess1 | AssetAccess2 | AssetAccess3]): + root: Annotated[ + AssetAccess1 | AssetAccess2 | AssetAccess3, + Field(description='Authentication for accessing secured asset URLs'), + ] + + +class Assets1(AdCPBaseModel): + access: Annotated[AssetAccess | None, Field(description='Authentication for secured URLs')] = ( + None + ) + alt_text: Annotated[str | None, Field(description='Alt text or image description')] = None + caption: Annotated[str | None, Field(description='Image caption')] = None + height: Annotated[int | None, Field(description='Image height in pixels')] = None + type: Literal['image'] + url: Annotated[AnyUrl, Field(description='Image URL')] + width: Annotated[int | None, Field(description='Image width in pixels')] = None + + +class Assets2(AdCPBaseModel): + access: Annotated[AssetAccess | None, Field(description='Authentication for secured URLs')] = ( + None + ) + duration_ms: Annotated[int | None, Field(description='Video duration in milliseconds')] = None + thumbnail_url: Annotated[AnyUrl | None, Field(description='Video thumbnail URL')] = None + transcript: Annotated[str | None, Field(description='Video transcript')] = None + transcript_source: Annotated[ + TranscriptSource | None, Field(description='How the transcript was generated') + ] = None + type: Literal['video'] + url: Annotated[AnyUrl, Field(description='Video URL')] + + +class Assets3(AdCPBaseModel): + access: Annotated[AssetAccess | None, Field(description='Authentication for secured URLs')] = ( + None + ) + duration_ms: Annotated[int | None, Field(description='Audio duration in milliseconds')] = None + transcript: Annotated[str | None, Field(description='Audio transcript')] = None + transcript_source: Annotated[ + TranscriptSource1 | None, Field(description='How the transcript was generated') + ] = None + type: Literal['audio'] + url: Annotated[AnyUrl, Field(description='Audio URL')] + + +class Artifact(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + artifact_id: Annotated[ + str, + Field( + description="Identifier for this artifact within the property. The property owner defines the scheme (e.g., 'article_12345', 'episode_42_segment_3', 'post_abc123')." + ), + ] + assets: Annotated[ + list[Assets | Assets1 | Assets2 | Assets3], + Field( + description='Artifact assets in document flow order - text blocks, images, video, audio' + ), + ] + format_id: Annotated[ + format_id_1.FormatId | None, + Field( + description='Optional reference to a format definition. Uses the same format registry as creative formats.' + ), + ] = None + identifiers: Annotated[ + Identifiers | None, Field(description='Platform-specific identifiers for this artifact') + ] = None + last_update_time: Annotated[ + AwareDatetime | None, + Field(description='When the artifact was last modified (ISO 8601 format)'), + ] = None + metadata: Annotated[ + Metadata | None, Field(description='Rich metadata extracted from the artifact') + ] = None + property_id: Annotated[ + identifier.Identifier, + Field(description='Identifier for the property where this artifact appears'), + ] + published_time: Annotated[ + AwareDatetime | None, Field(description='When the artifact was published (ISO 8601 format)') + ] = None + url: Annotated[ + AnyUrl | None, + Field( + description='Optional URL for this artifact (web page, podcast feed, video page). Not all artifacts have URLs (e.g., Instagram content, podcast segments, TV scenes).' + ), + ] = None + variant_id: Annotated[ + str | None, + Field( + description="Identifies a specific variant of this artifact. Use for A/B tests, translations, or temporal versions. Examples: 'en', 'es-MX', 'v2', 'headline_test_b'. The combination of artifact_id + variant_id must be unique." + ), + ] = None diff --git a/src/adcp/types/generated_poc/content_standards/artifact_webhook_payload.py b/src/adcp/types/generated_poc/content_standards/artifact_webhook_payload.py new file mode 100644 index 00000000..fc5bc2a5 --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/artifact_webhook_payload.py @@ -0,0 +1,64 @@ +# generated by datamodel-codegen: +# filename: content_standards/artifact_webhook_payload.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import AwareDatetime, ConfigDict, Field + +from ..core import ext as ext_1 +from . import artifact as artifact_1 + + +class Pagination(AdCPBaseModel): + batch_number: Annotated[int | None, Field(description='Current batch number (1-indexed)')] = ( + None + ) + total_artifacts: Annotated[ + int | None, Field(description='Total artifacts in the delivery period') + ] = None + total_batches: Annotated[ + int | None, Field(description='Total batches for this delivery period') + ] = None + + +class Artifact(AdCPBaseModel): + artifact: Annotated[artifact_1.Artifact, Field(description='The content artifact')] + delivered_at: Annotated[ + AwareDatetime, Field(description='When the impression was delivered (ISO 8601)') + ] + impression_id: Annotated[ + str | None, + Field(description='Optional impression identifier for correlation with delivery reports'), + ] = None + package_id: Annotated[ + str | None, Field(description='Package within the media buy this artifact relates to') + ] = None + + +class ArtifactWebhookPayload(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + artifacts: Annotated[ + list[Artifact], Field(description='Content artifacts from delivered impressions') + ] + batch_id: Annotated[ + str, + Field( + description='Unique identifier for this batch of artifacts. Use for deduplication and acknowledgment.' + ), + ] + ext: ext_1.ExtensionObject | None = None + media_buy_id: Annotated[ + str, Field(description='Media buy identifier these artifacts belong to') + ] + pagination: Annotated[ + Pagination | None, Field(description='Pagination info when batching large artifact sets') + ] = None + timestamp: Annotated[ + AwareDatetime, Field(description='When this batch was generated (ISO 8601)') + ] diff --git a/src/adcp/types/generated_poc/content_standards/calibrate_content_request.py b/src/adcp/types/generated_poc/content_standards/calibrate_content_request.py new file mode 100644 index 00000000..bb4ca8da --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/calibrate_content_request.py @@ -0,0 +1,17 @@ +# generated by datamodel-codegen: +# filename: content_standards/calibrate_content_request.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import Field + +from . import artifact as artifact_1 + + +class CalibrateContentRequest(AdCPBaseModel): + artifact: Annotated[artifact_1.Artifact, Field(description='Artifact to evaluate')] + standards_id: Annotated[str, Field(description='Standards configuration to calibrate against')] diff --git a/src/adcp/types/generated_poc/content_standards/calibrate_content_response.py b/src/adcp/types/generated_poc/content_standards/calibrate_content_response.py new file mode 100644 index 00000000..a96474e9 --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/calibrate_content_response.py @@ -0,0 +1,74 @@ +# generated by datamodel-codegen: +# filename: content_standards/calibrate_content_response.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated, Any + +from adcp.types.base import AdCPBaseModel +from pydantic import Field, RootModel + +from ..core import error + + +class Status(Enum): + passed = 'passed' + failed = 'failed' + warning = 'warning' + unevaluated = 'unevaluated' + + +class Feature(AdCPBaseModel): + explanation: Annotated[ + str | None, + Field(description='Human-readable explanation of why this feature passed or failed'), + ] = None + feature_id: Annotated[ + str, + Field( + description='Which feature was evaluated (e.g., brand_safety, brand_suitability, competitor_adjacency)' + ), + ] + status: Annotated[Status, Field(description='Evaluation status for this feature')] + + +class Verdict(Enum): + pass_ = 'pass' + fail = 'fail' + + +class CalibrateContentResponse1(AdCPBaseModel): + confidence: Annotated[ + float | None, Field(description='Model confidence in the verdict (0-1)', ge=0.0, le=1.0) + ] = None + errors: Annotated[ + Any | None, Field(description='Field must not be present in success response') + ] = None + explanation: Annotated[ + str | None, Field(description='Detailed natural language explanation of the decision') + ] = None + features: Annotated[ + list[Feature] | None, Field(description='Per-feature breakdown with explanations') + ] = None + verdict: Annotated[ + Verdict, Field(description='Overall pass/fail verdict for the content evaluation') + ] + + +class CalibrateContentResponse2(AdCPBaseModel): + errors: list[error.Error] + verdict: Annotated[ + Any | None, Field(description='Field must not be present in error response') + ] = None + + +class CalibrateContentResponse(RootModel[CalibrateContentResponse1 | CalibrateContentResponse2]): + root: Annotated[ + CalibrateContentResponse1 | CalibrateContentResponse2, + Field( + description='Response payload with verdict and detailed explanations for collaborative calibration', + title='Calibrate Content Response', + ), + ] diff --git a/src/adcp/types/generated_poc/content_standards/content_standards.py b/src/adcp/types/generated_poc/content_standards/content_standards.py new file mode 100644 index 00000000..9f1e619c --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/content_standards.py @@ -0,0 +1,66 @@ +# generated by datamodel-codegen: +# filename: content_standards/content_standards.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import Field + +from ..core import ext as ext_1 +from ..enums import channels +from . import artifact + + +class CalibrationExemplars(AdCPBaseModel): + fail: Annotated[ + list[artifact.Artifact] | None, + Field(description='Artifacts that fail the content standards'), + ] = None + pass_: Annotated[ + list[artifact.Artifact] | None, + Field(alias='pass', description='Artifacts that pass the content standards'), + ] = None + + +class ContentStandards(AdCPBaseModel): + calibration_exemplars: Annotated[ + CalibrationExemplars | None, + Field( + description='Training/test set to calibrate policy interpretation. Provides concrete examples of pass/fail decisions.' + ), + ] = None + channels_any: Annotated[ + list[channels.MediaChannel] | None, + Field( + description='Advertising channels. Standards apply to ANY of the listed channels (OR logic).' + ), + ] = None + countries_all: Annotated[ + list[str] | None, + Field( + description='ISO 3166-1 alpha-2 country codes. Standards apply in ALL listed countries (AND logic).' + ), + ] = None + ext: ext_1.ExtensionObject | None = None + languages_any: Annotated[ + list[str] | None, + Field( + description="BCP 47 language tags (e.g., 'en', 'de', 'fr'). Standards apply to content in ANY of these languages (OR logic). Content in unlisted languages is not covered by these standards.", + min_length=1, + ), + ] = None + name: Annotated[ + str | None, Field(description='Human-readable name for this standards configuration') + ] = None + policy: Annotated[ + str | None, + Field( + description='Natural language policy describing acceptable and unacceptable content contexts. Used by LLMs and human reviewers to make judgments.' + ), + ] = None + standards_id: Annotated[ + str, Field(description='Unique identifier for this standards configuration') + ] diff --git a/src/adcp/types/generated_poc/content_standards/create_content_standards_request.py b/src/adcp/types/generated_poc/content_standards/create_content_standards_request.py new file mode 100644 index 00000000..402d1f0a --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/create_content_standards_request.py @@ -0,0 +1,97 @@ +# generated by datamodel-codegen: +# filename: content_standards/create_content_standards_request.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated, Literal + +from adcp.types.base import AdCPBaseModel +from pydantic import AnyUrl, ConfigDict, Field + +from ..core import context as context_1 +from ..core import ext as ext_1 +from ..enums import channels +from . import artifact + + +class Fail(AdCPBaseModel): + language: Annotated[ + str | None, Field(description='BCP 47 language tag for content at this URL') + ] = None + type: Annotated[Literal['url'], Field(description='Indicates this is a URL reference')] + value: Annotated[ + AnyUrl, + Field( + description="Full URL to a specific page (e.g., 'https://news.example.com/controversial-article')" + ), + ] + + +class Pass(AdCPBaseModel): + language: Annotated[ + str | None, Field(description='BCP 47 language tag for content at this URL') + ] = None + type: Annotated[Literal['url'], Field(description='Indicates this is a URL reference')] + value: Annotated[ + AnyUrl, + Field( + description="Full URL to a specific page (e.g., 'https://espn.com/nba/story/_/id/12345/lakers-win')" + ), + ] + + +class Scope(AdCPBaseModel): + channels_any: Annotated[ + list[channels.MediaChannel] | None, + Field( + description='Advertising channels. Standards apply to ANY of the listed channels (OR logic).' + ), + ] = None + countries_all: Annotated[ + list[str] | None, + Field( + description='ISO 3166-1 alpha-2 country codes. Standards apply in ALL listed countries (AND logic).' + ), + ] = None + description: Annotated[ + str | None, Field(description='Human-readable description of this scope') + ] = None + languages_any: Annotated[ + list[str], + Field( + description="BCP 47 language tags (e.g., 'en', 'de', 'fr'). Standards apply to content in ANY of these languages (OR logic). Content in unlisted languages is not covered by these standards.", + min_length=1, + ), + ] + + +class CalibrationExemplars(AdCPBaseModel): + fail: Annotated[ + list[Fail | artifact.Artifact] | None, Field(description='Content that fails the standards') + ] = None + pass_: Annotated[ + list[Pass | artifact.Artifact] | None, + Field(alias='pass', description='Content that passes the standards'), + ] = None + + +class CreateContentStandardsRequest(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + calibration_exemplars: Annotated[ + CalibrationExemplars | None, + Field( + description='Training/test set to calibrate policy interpretation. Use URL references for pages to be fetched and analyzed, or full artifacts for pre-extracted content.' + ), + ] = None + context: context_1.ContextObject | None = None + ext: ext_1.ExtensionObject | None = None + policy: Annotated[ + str, + Field( + description='Natural language policy describing acceptable and unacceptable content contexts. Used by LLMs and human reviewers to make judgments.' + ), + ] + scope: Annotated[Scope, Field(description='Where this standards configuration applies')] diff --git a/src/adcp/types/generated_poc/content_standards/create_content_standards_response.py b/src/adcp/types/generated_poc/content_standards/create_content_standards_response.py new file mode 100644 index 00000000..19bbe2c5 --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/create_content_standards_response.py @@ -0,0 +1,52 @@ +# generated by datamodel-codegen: +# filename: content_standards/create_content_standards_response.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated, Any + +from adcp.types.base import AdCPBaseModel +from pydantic import Field, RootModel + +from ..core import context as context_1 +from ..core import error +from ..core import ext as ext_1 + + +class CreateContentStandardsResponse1(AdCPBaseModel): + context: context_1.ContextObject | None = None + errors: Annotated[ + Any | None, Field(description='Field must not be present in success response') + ] = None + ext: ext_1.ExtensionObject | None = None + standards_id: Annotated[ + str, Field(description='Unique identifier for the created standards configuration') + ] + + +class CreateContentStandardsResponse2(AdCPBaseModel): + conflicting_standards_id: Annotated[ + str | None, + Field( + description='If the error is a scope conflict, the ID of the existing standards that conflict' + ), + ] = None + context: context_1.ContextObject | None = None + errors: list[error.Error] + ext: ext_1.ExtensionObject | None = None + standards_id: Annotated[ + Any | None, Field(description='Field must not be present in error response') + ] = None + + +class CreateContentStandardsResponse( + RootModel[CreateContentStandardsResponse1 | CreateContentStandardsResponse2] +): + root: Annotated[ + CreateContentStandardsResponse1 | CreateContentStandardsResponse2, + Field( + description='Response payload for creating a content standards configuration', + title='Create Content Standards Response', + ), + ] diff --git a/src/adcp/types/generated_poc/content_standards/get_content_standards_request.py b/src/adcp/types/generated_poc/content_standards/get_content_standards_request.py new file mode 100644 index 00000000..bef472fb --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/get_content_standards_request.py @@ -0,0 +1,21 @@ +# generated by datamodel-codegen: +# filename: content_standards/get_content_standards_request.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import Field + +from ..core import context as context_1 +from ..core import ext as ext_1 + + +class GetContentStandardsRequest(AdCPBaseModel): + context: context_1.ContextObject | None = None + ext: ext_1.ExtensionObject | None = None + standards_id: Annotated[ + str, Field(description='Identifier for the standards configuration to retrieve') + ] diff --git a/src/adcp/types/generated_poc/content_standards/get_content_standards_response.py b/src/adcp/types/generated_poc/content_standards/get_content_standards_response.py new file mode 100644 index 00000000..b715c091 --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/get_content_standards_response.py @@ -0,0 +1,43 @@ +# generated by datamodel-codegen: +# filename: content_standards/get_content_standards_response.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated, Any + +from adcp.types.base import AdCPBaseModel +from pydantic import Field, RootModel + +from ..core import context as context_1 +from ..core import error +from ..core import ext as ext_1 +from .content_standards import ContentStandards + + +class GetContentStandardsResponse2(AdCPBaseModel): + context: context_1.ContextObject | None = None + errors: list[error.Error] + ext: ext_1.ExtensionObject | None = None + standards_id: Annotated[ + Any | None, Field(description='Field must not be present in error response') + ] = None + + +class GetContentStandardsResponse1(ContentStandards): + context: context_1.ContextObject | None = None + errors: Annotated[ + Any | None, Field(description='Field must not be present in success response') + ] = None + + +class GetContentStandardsResponse( + RootModel[GetContentStandardsResponse1 | GetContentStandardsResponse2] +): + root: Annotated[ + GetContentStandardsResponse1 | GetContentStandardsResponse2, + Field( + description='Response payload with content safety policies', + title='Get Content Standards Response', + ), + ] diff --git a/src/adcp/types/generated_poc/content_standards/get_media_buy_artifacts_request.py b/src/adcp/types/generated_poc/content_standards/get_media_buy_artifacts_request.py new file mode 100644 index 00000000..e74b0ca7 --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/get_media_buy_artifacts_request.py @@ -0,0 +1,64 @@ +# generated by datamodel-codegen: +# filename: content_standards/get_media_buy_artifacts_request.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import AwareDatetime, Field + +from ..core import context as context_1 +from ..core import ext as ext_1 + + +class Method(Enum): + random = 'random' + stratified = 'stratified' + recent = 'recent' + failures_only = 'failures_only' + + +class Sampling(AdCPBaseModel): + method: Annotated[Method | None, Field(description='How to select the sample')] = None + rate: Annotated[ + float | None, + Field( + description='Sampling rate (0-1). 1.0 = all deliveries, 0.25 = 25% sample.', + ge=0.0, + le=1.0, + ), + ] = None + + +class TimeRange(AdCPBaseModel): + end: Annotated[AwareDatetime | None, Field(description='End of time range (exclusive)')] = None + start: Annotated[AwareDatetime | None, Field(description='Start of time range (inclusive)')] = ( + None + ) + + +class GetMediaBuyArtifactsRequest(AdCPBaseModel): + context: context_1.ContextObject | None = None + cursor: Annotated[ + str | None, Field(description='Pagination cursor for fetching subsequent pages') + ] = None + ext: ext_1.ExtensionObject | None = None + limit: Annotated[ + int | None, Field(description='Maximum artifacts to return per request', ge=1, le=10000) + ] = 1000 + media_buy_id: Annotated[str, Field(description='Media buy to get artifacts from')] + package_ids: Annotated[ + list[str] | None, Field(description='Filter to specific packages within the media buy') + ] = None + sampling: Annotated[ + Sampling | None, + Field( + description='Sampling parameters. Defaults to the sampling rate agreed in the media buy.' + ), + ] = None + time_range: Annotated[TimeRange | None, Field(description='Filter to specific time period')] = ( + None + ) diff --git a/src/adcp/types/generated_poc/content_standards/get_media_buy_artifacts_response.py b/src/adcp/types/generated_poc/content_standards/get_media_buy_artifacts_response.py new file mode 100644 index 00000000..a127a48f --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/get_media_buy_artifacts_response.py @@ -0,0 +1,117 @@ +# generated by datamodel-codegen: +# filename: content_standards/get_media_buy_artifacts_response.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated, Any + +from adcp.types.base import AdCPBaseModel +from pydantic import AwareDatetime, Field, RootModel + +from ..core import context as context_1 +from ..core import error +from ..core import ext as ext_1 +from . import artifact as artifact_1 + + +class BrandContext(AdCPBaseModel): + brand_id: Annotated[str | None, Field(description='Brand identifier')] = None + sku_id: Annotated[str | None, Field(description='Product/SKU identifier if applicable')] = None + + +class LocalVerdict(Enum): + pass_ = 'pass' + fail = 'fail' + unevaluated = 'unevaluated' + + +class Pagination(AdCPBaseModel): + cursor: Annotated[str | None, Field(description='Cursor for fetching the next page')] = None + has_more: Annotated[bool | None, Field(description='Whether more results are available')] = None + + +class Method(Enum): + random = 'random' + stratified = 'stratified' + recent = 'recent' + failures_only = 'failures_only' + + +class SamplingInfo(AdCPBaseModel): + effective_rate: Annotated[float | None, Field(description='Actual sampling rate achieved')] = ( + None + ) + method: Annotated[Method | None, Field(description='Sampling method used')] = None + sampled_count: Annotated[ + int | None, Field(description='Number of artifacts in this response') + ] = None + total_deliveries: Annotated[ + int | None, Field(description='Total deliveries in the time range') + ] = None + + +class GetMediaBuyArtifactsResponse2(AdCPBaseModel): + context: context_1.ContextObject | None = None + errors: list[error.Error] + ext: ext_1.ExtensionObject | None = None + media_buy_id: Annotated[ + Any | None, Field(description='Field must not be present in error response') + ] = None + + +class Artifact(AdCPBaseModel): + artifact: Annotated[artifact_1.Artifact, Field(description='Full artifact with content assets')] + brand_context: Annotated[ + BrandContext | None, + Field( + description='Brand information for policy evaluation. Schema TBD - placeholder for brand identifiers.' + ), + ] = None + channel: Annotated[ + str | None, Field(description='Channel type (e.g., display, video, audio, social)') + ] = None + country: Annotated[ + str | None, Field(description='ISO 3166-1 alpha-2 country code where delivery occurred') + ] = None + local_verdict: Annotated[ + LocalVerdict | None, Field(description="Seller's local model verdict for this artifact") + ] = None + package_id: Annotated[ + str | None, Field(description='Which package this delivery belongs to') + ] = None + record_id: Annotated[str, Field(description='Unique identifier for this delivery record')] + timestamp: Annotated[AwareDatetime | None, Field(description='When the delivery occurred')] = ( + None + ) + + +class GetMediaBuyArtifactsResponse1(AdCPBaseModel): + artifacts: Annotated[ + list[Artifact], Field(description='Delivery records with full artifact content') + ] + context: context_1.ContextObject | None = None + errors: Annotated[ + Any | None, Field(description='Field must not be present in success response') + ] = None + ext: ext_1.ExtensionObject | None = None + media_buy_id: Annotated[str, Field(description='Media buy these artifacts belong to')] + pagination: Annotated[ + Pagination | None, Field(description='Pagination information for large result sets') + ] = None + sampling_info: Annotated[ + SamplingInfo | None, Field(description='Information about how the sample was generated') + ] = None + + +class GetMediaBuyArtifactsResponse( + RootModel[GetMediaBuyArtifactsResponse1 | GetMediaBuyArtifactsResponse2] +): + root: Annotated[ + GetMediaBuyArtifactsResponse1 | GetMediaBuyArtifactsResponse2, + Field( + description='Response containing content artifacts from a media buy for validation', + title='Get Media Buy Artifacts Response', + ), + ] diff --git a/src/adcp/types/generated_poc/content_standards/list_content_standards_request.py b/src/adcp/types/generated_poc/content_standards/list_content_standards_request.py new file mode 100644 index 00000000..b46d022f --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/list_content_standards_request.py @@ -0,0 +1,31 @@ +# generated by datamodel-codegen: +# filename: content_standards/list_content_standards_request.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field + +from ..core import context as context_1 +from ..core import ext as ext_1 +from ..enums import channels as channels_1 + + +class ListContentStandardsRequest(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + channels: Annotated[ + list[channels_1.MediaChannel] | None, Field(description='Filter by channel') + ] = None + context: context_1.ContextObject | None = None + countries: Annotated[ + list[str] | None, Field(description='Filter by ISO 3166-1 alpha-2 country codes') + ] = None + ext: ext_1.ExtensionObject | None = None + languages: Annotated[list[str] | None, Field(description='Filter by BCP 47 language tags')] = ( + None + ) diff --git a/src/adcp/types/generated_poc/content_standards/list_content_standards_response.py b/src/adcp/types/generated_poc/content_standards/list_content_standards_response.py new file mode 100644 index 00000000..3c216ca0 --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/list_content_standards_response.py @@ -0,0 +1,48 @@ +# generated by datamodel-codegen: +# filename: content_standards/list_content_standards_response.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated, Any + +from adcp.types.base import AdCPBaseModel +from pydantic import Field, RootModel + +from ..core import context as context_1 +from ..core import error +from ..core import ext as ext_1 +from . import content_standards + + +class ListContentStandardsResponse2(AdCPBaseModel): + context: context_1.ContextObject | None = None + errors: list[error.Error] + ext: ext_1.ExtensionObject | None = None + standards: Annotated[ + Any | None, Field(description='Field must not be present in error response') + ] = None + + +class ListContentStandardsResponse1(AdCPBaseModel): + context: context_1.ContextObject | None = None + errors: Annotated[ + Any | None, Field(description='Field must not be present in success response') + ] = None + ext: ext_1.ExtensionObject | None = None + standards: Annotated[ + list[content_standards.ContentStandards], + Field(description='Array of content standards configurations matching the filter criteria'), + ] + + +class ListContentStandardsResponse( + RootModel[ListContentStandardsResponse1 | ListContentStandardsResponse2] +): + root: Annotated[ + ListContentStandardsResponse1 | ListContentStandardsResponse2, + Field( + description='Response payload with list of content standards configurations', + title='List Content Standards Response', + ), + ] diff --git a/src/adcp/types/generated_poc/content_standards/update_content_standards_request.py b/src/adcp/types/generated_poc/content_standards/update_content_standards_request.py new file mode 100644 index 00000000..a308624c --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/update_content_standards_request.py @@ -0,0 +1,101 @@ +# generated by datamodel-codegen: +# filename: content_standards/update_content_standards_request.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated, Literal + +from adcp.types.base import AdCPBaseModel +from pydantic import AnyUrl, ConfigDict, Field + +from ..core import context as context_1 +from ..core import ext as ext_1 +from ..enums import channels +from . import artifact + + +class Fail(AdCPBaseModel): + language: Annotated[ + str | None, Field(description='BCP 47 language tag for content at this URL') + ] = None + type: Annotated[Literal['url'], Field(description='Indicates this is a URL reference')] + value: Annotated[ + AnyUrl, + Field( + description="Full URL to a specific page (e.g., 'https://news.example.com/controversial-article')" + ), + ] + + +class Pass(AdCPBaseModel): + language: Annotated[ + str | None, Field(description='BCP 47 language tag for content at this URL') + ] = None + type: Annotated[Literal['url'], Field(description='Indicates this is a URL reference')] + value: Annotated[ + AnyUrl, + Field( + description="Full URL to a specific page (e.g., 'https://espn.com/nba/story/_/id/12345/lakers-win')" + ), + ] + + +class Scope(AdCPBaseModel): + channels_any: Annotated[ + list[channels.MediaChannel] | None, + Field( + description='Advertising channels. Standards apply to ANY of the listed channels (OR logic).' + ), + ] = None + countries_all: Annotated[ + list[str] | None, + Field( + description='ISO 3166-1 alpha-2 country codes. Standards apply in ALL listed countries (AND logic).' + ), + ] = None + description: Annotated[ + str | None, Field(description='Human-readable description of this scope') + ] = None + languages_any: Annotated[ + list[str] | None, + Field( + description="BCP 47 language tags (e.g., 'en', 'de', 'fr'). Standards apply to content in ANY of these languages (OR logic). Content in unlisted languages is not covered by these standards.", + min_length=1, + ), + ] = None + + +class CalibrationExemplars(AdCPBaseModel): + fail: Annotated[ + list[Fail | artifact.Artifact] | None, Field(description='Content that fails the standards') + ] = None + pass_: Annotated[ + list[Pass | artifact.Artifact] | None, + Field(alias='pass', description='Content that passes the standards'), + ] = None + + +class UpdateContentStandardsRequest(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + calibration_exemplars: Annotated[ + CalibrationExemplars | None, + Field( + description='Updated training/test set to calibrate policy interpretation. Use URL references for pages to be fetched and analyzed, or full artifacts for pre-extracted content.' + ), + ] = None + context: context_1.ContextObject | None = None + ext: ext_1.ExtensionObject | None = None + policy: Annotated[ + str | None, + Field( + description='Updated natural language policy describing acceptable and unacceptable content contexts.' + ), + ] = None + scope: Annotated[ + Scope | None, + Field(description='Updated scope for where this standards configuration applies'), + ] = None + standards_id: Annotated[str, Field(description='ID of the standards configuration to update')] diff --git a/src/adcp/types/generated_poc/content_standards/update_content_standards_response.py b/src/adcp/types/generated_poc/content_standards/update_content_standards_response.py new file mode 100644 index 00000000..bb9f0505 --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/update_content_standards_response.py @@ -0,0 +1,40 @@ +# generated by datamodel-codegen: +# filename: content_standards/update_content_standards_response.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field + +from ..core import context as context_1 +from ..core import ext as ext_1 + + +class Error(AdCPBaseModel): + code: Annotated[ + str, Field(description='Error code (e.g., STANDARDS_NOT_FOUND, SCOPE_CONFLICT)') + ] + message: Annotated[str, Field(description='Human-readable error message')] + + +class UpdateContentStandardsResponse(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + conflicting_standards_id: Annotated[ + str | None, + Field( + description='If scope change conflicts with another configuration, the ID of the conflicting standards' + ), + ] = None + context: context_1.ContextObject | None = None + errors: Annotated[ + list[Error] | None, Field(description='Errors that occurred during the update') + ] = None + ext: ext_1.ExtensionObject | None = None + standards_id: Annotated[ + str | None, Field(description='ID of the updated standards configuration') + ] = None diff --git a/src/adcp/types/generated_poc/content_standards/validate_content_delivery_request.py b/src/adcp/types/generated_poc/content_standards/validate_content_delivery_request.py new file mode 100644 index 00000000..dc364220 --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/validate_content_delivery_request.py @@ -0,0 +1,59 @@ +# generated by datamodel-codegen: +# filename: content_standards/validate_content_delivery_request.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import AwareDatetime, Field + +from ..core import context as context_1 +from ..core import ext as ext_1 +from . import artifact as artifact_1 + + +class BrandContext(AdCPBaseModel): + brand_id: Annotated[str | None, Field(description='Brand identifier')] = None + sku_id: Annotated[str | None, Field(description='Product/SKU identifier if applicable')] = None + + +class Record(AdCPBaseModel): + artifact: Annotated[artifact_1.Artifact, Field(description='Artifact where ad was delivered')] + brand_context: Annotated[ + BrandContext | None, + Field( + description='Brand information for policy evaluation. Schema TBD - placeholder for brand identifiers.' + ), + ] = None + channel: Annotated[ + str | None, Field(description='Channel type (e.g., display, video, audio, social)') + ] = None + country: Annotated[ + str | None, Field(description='ISO 3166-1 alpha-2 country code where delivery occurred') + ] = None + media_buy_id: Annotated[ + str | None, + Field(description='Media buy this record belongs to (when batching across multiple buys)'), + ] = None + record_id: Annotated[str, Field(description='Unique identifier for this delivery record')] + timestamp: Annotated[AwareDatetime | None, Field(description='When the delivery occurred')] = ( + None + ) + + +class ValidateContentDeliveryRequest(AdCPBaseModel): + context: context_1.ContextObject | None = None + ext: ext_1.ExtensionObject | None = None + feature_ids: Annotated[ + list[str] | None, Field(description='Specific features to evaluate (defaults to all)') + ] = None + include_passed: Annotated[ + bool | None, Field(description='Include passed records in results') + ] = True + records: Annotated[ + list[Record], + Field(description='Delivery records to validate (max 10,000)', max_length=10000), + ] + standards_id: Annotated[str, Field(description='Standards configuration to validate against')] diff --git a/src/adcp/types/generated_poc/content_standards/validate_content_delivery_response.py b/src/adcp/types/generated_poc/content_standards/validate_content_delivery_response.py new file mode 100644 index 00000000..0b5f68e4 --- /dev/null +++ b/src/adcp/types/generated_poc/content_standards/validate_content_delivery_response.py @@ -0,0 +1,85 @@ +# generated by datamodel-codegen: +# filename: content_standards/validate_content_delivery_response.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated, Any + +from adcp.types.base import AdCPBaseModel +from pydantic import Field, RootModel + +from ..core import context as context_1 +from ..core import error +from ..core import ext as ext_1 + + +class Status(Enum): + passed = 'passed' + failed = 'failed' + warning = 'warning' + unevaluated = 'unevaluated' + + +class Feature(AdCPBaseModel): + feature_id: str + message: str | None = None + rule_id: Annotated[ + str | None, + Field( + description='Which rule triggered this result (e.g., GARM category, Scope3 standard)' + ), + ] = None + status: Status + value: Any | None = None + + +class Verdict(Enum): + pass_ = 'pass' + fail = 'fail' + + +class Result(AdCPBaseModel): + features: Annotated[ + list[Feature] | None, Field(description='Optional feature-level breakdown') + ] = None + record_id: Annotated[str, Field(description='Which delivery record was evaluated')] + verdict: Annotated[Verdict, Field(description='Overall pass/fail verdict for this record')] + + +class Summary(AdCPBaseModel): + failed_records: int + passed_records: int + total_records: int + + +class ValidateContentDeliveryResponse1(AdCPBaseModel): + context: context_1.ContextObject | None = None + errors: Annotated[ + Any | None, Field(description='Field must not be present in success response') + ] = None + ext: ext_1.ExtensionObject | None = None + results: Annotated[list[Result], Field(description='Per-record evaluation results')] + summary: Annotated[Summary, Field(description='Summary counts across all records')] + + +class ValidateContentDeliveryResponse2(AdCPBaseModel): + context: context_1.ContextObject | None = None + errors: list[error.Error] + ext: ext_1.ExtensionObject | None = None + summary: Annotated[ + Any | None, Field(description='Field must not be present in error response') + ] = None + + +class ValidateContentDeliveryResponse( + RootModel[ValidateContentDeliveryResponse1 | ValidateContentDeliveryResponse2] +): + root: Annotated[ + ValidateContentDeliveryResponse1 | ValidateContentDeliveryResponse2, + Field( + description='Response payload with per-record verdicts and optional feature breakdown', + title='Validate Content Delivery Response', + ), + ] diff --git a/src/adcp/types/generated_poc/core/activation_key.py b/src/adcp/types/generated_poc/core/activation_key.py index 42d753d8..9d727326 100644 --- a/src/adcp/types/generated_poc/core/activation_key.py +++ b/src/adcp/types/generated_poc/core/activation_key.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/activation_key.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,22 +12,22 @@ class ActivationKey1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) segment_id: Annotated[ str, - Field(description="The platform-specific segment identifier to use in campaign targeting"), + Field(description='The platform-specific segment identifier to use in campaign targeting'), ] - type: Annotated[Literal["segment_id"], Field(description="Segment ID based targeting")] + type: Annotated[Literal['segment_id'], Field(description='Segment ID based targeting')] class ActivationKey2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - key: Annotated[str, Field(description="The targeting parameter key")] - type: Annotated[Literal["key_value"], Field(description="Key-value pair based targeting")] - value: Annotated[str, Field(description="The targeting parameter value")] + key: Annotated[str, Field(description='The targeting parameter key')] + type: Annotated[Literal['key_value'], Field(description='Key-value pair based targeting')] + value: Annotated[str, Field(description='The targeting parameter value')] class ActivationKey(RootModel[ActivationKey1 | ActivationKey2]): @@ -35,6 +35,6 @@ class ActivationKey(RootModel[ActivationKey1 | ActivationKey2]): ActivationKey1 | ActivationKey2, Field( description="Universal identifier for using a signal on a destination platform. Can be either a segment ID or a key-value pair depending on the platform's targeting mechanism.", - title="Activation Key", + title='Activation Key', ), ] diff --git a/src/adcp/types/generated_poc/core/assets/audio_asset.py b/src/adcp/types/generated_poc/core/assets/audio_asset.py index de9a645d..c3bf7bb5 100644 --- a/src/adcp/types/generated_poc/core/assets/audio_asset.py +++ b/src/adcp/types/generated_poc/core/assets/audio_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/audio_asset.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,15 +12,15 @@ class AudioAsset(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) bitrate_kbps: Annotated[ - int | None, Field(description="Audio bitrate in kilobits per second", ge=1) + int | None, Field(description='Audio bitrate in kilobits per second', ge=1) ] = None duration_ms: Annotated[ - int | None, Field(description="Audio duration in milliseconds", ge=0) + int | None, Field(description='Audio duration in milliseconds', ge=0) ] = None - format: Annotated[str | None, Field(description="Audio file format (mp3, wav, aac, etc.)")] = ( + format: Annotated[str | None, Field(description='Audio file format (mp3, wav, aac, etc.)')] = ( None ) - url: Annotated[AnyUrl, Field(description="URL to the audio asset")] + url: Annotated[AnyUrl, Field(description='URL to the audio asset')] diff --git a/src/adcp/types/generated_poc/core/assets/css_asset.py b/src/adcp/types/generated_poc/core/assets/css_asset.py index 64f8d30d..99c2ede5 100644 --- a/src/adcp/types/generated_poc/core/assets/css_asset.py +++ b/src/adcp/types/generated_poc/core/assets/css_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/css_asset.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,9 +12,9 @@ class CssAsset(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - content: Annotated[str, Field(description="CSS content")] + content: Annotated[str, Field(description='CSS content')] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") ] = None diff --git a/src/adcp/types/generated_poc/core/assets/daast_asset.py b/src/adcp/types/generated_poc/core/assets/daast_asset.py index c31154f4..5dcc7c27 100644 --- a/src/adcp/types/generated_poc/core/assets/daast_asset.py +++ b/src/adcp/types/generated_poc/core/assets/daast_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/daast_asset.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,49 +15,49 @@ class DaastAsset1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) companion_ads: Annotated[ - bool | None, Field(description="Whether companion display ads are included") + bool | None, Field(description='Whether companion display ads are included') ] = None daast_version: Annotated[ - daast_version_1.DaastVersion | None, Field(description="DAAST specification version") + daast_version_1.DaastVersion | None, Field(description='DAAST specification version') ] = None delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + Literal['url'], + Field(description='Discriminator indicating DAAST is delivered via URL endpoint'), ] duration_ms: Annotated[ - int | None, Field(description="Expected audio duration in milliseconds (if known)", ge=0) + int | None, Field(description='Expected audio duration in milliseconds (if known)', ge=0) ] = None tracking_events: Annotated[ list[daast_tracking_event.DaastTrackingEvent] | None, - Field(description="Tracking events supported by this DAAST tag"), + Field(description='Tracking events supported by this DAAST tag'), ] = None - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + url: Annotated[AnyUrl, Field(description='URL endpoint that returns DAAST XML')] class DaastAsset2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) companion_ads: Annotated[ - bool | None, Field(description="Whether companion display ads are included") + bool | None, Field(description='Whether companion display ads are included') ] = None - content: Annotated[str, Field(description="Inline DAAST XML content")] + content: Annotated[str, Field(description='Inline DAAST XML content')] daast_version: Annotated[ - daast_version_1.DaastVersion | None, Field(description="DAAST specification version") + daast_version_1.DaastVersion | None, Field(description='DAAST specification version') ] = None delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + Literal['inline'], + Field(description='Discriminator indicating DAAST is delivered as inline XML content'), ] duration_ms: Annotated[ - int | None, Field(description="Expected audio duration in milliseconds (if known)", ge=0) + int | None, Field(description='Expected audio duration in milliseconds (if known)', ge=0) ] = None tracking_events: Annotated[ list[daast_tracking_event.DaastTrackingEvent] | None, - Field(description="Tracking events supported by this DAAST tag"), + Field(description='Tracking events supported by this DAAST tag'), ] = None @@ -65,7 +65,7 @@ class DaastAsset(RootModel[DaastAsset1 | DaastAsset2]): root: Annotated[ DaastAsset1 | DaastAsset2, Field( - description="DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", - title="DAAST Asset", + description='DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving', + title='DAAST Asset', ), ] diff --git a/src/adcp/types/generated_poc/core/assets/html_asset.py b/src/adcp/types/generated_poc/core/assets/html_asset.py index dfc6c2c7..b5478158 100644 --- a/src/adcp/types/generated_poc/core/assets/html_asset.py +++ b/src/adcp/types/generated_poc/core/assets/html_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/html_asset.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class HtmlAsset(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - content: Annotated[str, Field(description="HTML content")] + content: Annotated[str, Field(description='HTML content')] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None diff --git a/src/adcp/types/generated_poc/core/assets/image_asset.py b/src/adcp/types/generated_poc/core/assets/image_asset.py index 773e530e..bffeb393 100644 --- a/src/adcp/types/generated_poc/core/assets/image_asset.py +++ b/src/adcp/types/generated_poc/core/assets/image_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/image_asset.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,12 +12,12 @@ class ImageAsset(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - alt_text: Annotated[str | None, Field(description="Alternative text for accessibility")] = None + alt_text: Annotated[str | None, Field(description='Alternative text for accessibility')] = None format: Annotated[ - str | None, Field(description="Image file format (jpg, png, gif, webp, etc.)") + str | None, Field(description='Image file format (jpg, png, gif, webp, etc.)') ] = None - height: Annotated[int, Field(description="Height in pixels", ge=1)] - url: Annotated[AnyUrl, Field(description="URL to the image asset")] - width: Annotated[int, Field(description="Width in pixels", ge=1)] + height: Annotated[int, Field(description='Height in pixels', ge=1)] + url: Annotated[AnyUrl, Field(description='URL to the image asset')] + width: Annotated[int, Field(description='Width in pixels', ge=1)] diff --git a/src/adcp/types/generated_poc/core/assets/javascript_asset.py b/src/adcp/types/generated_poc/core/assets/javascript_asset.py index 8c95b766..5b718248 100644 --- a/src/adcp/types/generated_poc/core/assets/javascript_asset.py +++ b/src/adcp/types/generated_poc/core/assets/javascript_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/javascript_asset.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,10 +14,10 @@ class JavascriptAsset(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - content: Annotated[str, Field(description="JavaScript content")] + content: Annotated[str, Field(description='JavaScript content')] module_type: Annotated[ javascript_module_type.JavascriptModuleType | None, - Field(description="JavaScript module type"), + Field(description='JavaScript module type'), ] = None diff --git a/src/adcp/types/generated_poc/core/assets/text_asset.py b/src/adcp/types/generated_poc/core/assets/text_asset.py index 553bd887..991578dd 100644 --- a/src/adcp/types/generated_poc/core/assets/text_asset.py +++ b/src/adcp/types/generated_poc/core/assets/text_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/text_asset.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,9 +12,9 @@ class TextAsset(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - content: Annotated[str, Field(description="Text content")] + content: Annotated[str, Field(description='Text content')] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None ) diff --git a/src/adcp/types/generated_poc/core/assets/url_asset.py b/src/adcp/types/generated_poc/core/assets/url_asset.py index 10707be5..b57df169 100644 --- a/src/adcp/types/generated_poc/core/assets/url_asset.py +++ b/src/adcp/types/generated_poc/core/assets/url_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/url_asset.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,12 +14,12 @@ class UrlAsset(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) description: Annotated[ - str | None, Field(description="Description of what this URL points to") + str | None, Field(description='Description of what this URL points to') ] = None - url: Annotated[AnyUrl, Field(description="URL reference")] + url: Annotated[AnyUrl, Field(description='URL reference')] url_type: Annotated[ url_asset_type.UrlAssetType | None, Field( diff --git a/src/adcp/types/generated_poc/core/assets/vast_asset.py b/src/adcp/types/generated_poc/core/assets/vast_asset.py index bbe8187e..d84d1c23 100644 --- a/src/adcp/types/generated_poc/core/assets/vast_asset.py +++ b/src/adcp/types/generated_poc/core/assets/vast_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/vast_asset.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,51 +15,51 @@ class VastAsset1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + Literal['url'], + Field(description='Discriminator indicating VAST is delivered via URL endpoint'), ] duration_ms: Annotated[ - int | None, Field(description="Expected video duration in milliseconds (if known)", ge=0) + int | None, Field(description='Expected video duration in milliseconds (if known)', ge=0) ] = None tracking_events: Annotated[ list[vast_tracking_event.VastTrackingEvent] | None, - Field(description="Tracking events supported by this VAST tag"), + Field(description='Tracking events supported by this VAST tag'), ] = None - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + url: Annotated[AnyUrl, Field(description='URL endpoint that returns VAST XML')] vast_version: Annotated[ - vast_version_1.VastVersion | None, Field(description="VAST specification version") + vast_version_1.VastVersion | None, Field(description='VAST specification version') ] = None vpaid_enabled: Annotated[ bool | None, - Field(description="Whether VPAID (Video Player-Ad Interface Definition) is supported"), + Field(description='Whether VPAID (Video Player-Ad Interface Definition) is supported'), ] = None class VastAsset2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - content: Annotated[str, Field(description="Inline VAST XML content")] + content: Annotated[str, Field(description='Inline VAST XML content')] delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), + Literal['inline'], + Field(description='Discriminator indicating VAST is delivered as inline XML content'), ] duration_ms: Annotated[ - int | None, Field(description="Expected video duration in milliseconds (if known)", ge=0) + int | None, Field(description='Expected video duration in milliseconds (if known)', ge=0) ] = None tracking_events: Annotated[ list[vast_tracking_event.VastTrackingEvent] | None, - Field(description="Tracking events supported by this VAST tag"), + Field(description='Tracking events supported by this VAST tag'), ] = None vast_version: Annotated[ - vast_version_1.VastVersion | None, Field(description="VAST specification version") + vast_version_1.VastVersion | None, Field(description='VAST specification version') ] = None vpaid_enabled: Annotated[ bool | None, - Field(description="Whether VPAID (Video Player-Ad Interface Definition) is supported"), + Field(description='Whether VPAID (Video Player-Ad Interface Definition) is supported'), ] = None @@ -67,7 +67,7 @@ class VastAsset(RootModel[VastAsset1 | VastAsset2]): root: Annotated[ VastAsset1 | VastAsset2, Field( - description="VAST (Video Ad Serving Template) tag for third-party video ad serving", - title="VAST Asset", + description='VAST (Video Ad Serving Template) tag for third-party video ad serving', + title='VAST Asset', ), ] diff --git a/src/adcp/types/generated_poc/core/assets/video_asset.py b/src/adcp/types/generated_poc/core/assets/video_asset.py index 259ba5f1..ae98613a 100644 --- a/src/adcp/types/generated_poc/core/assets/video_asset.py +++ b/src/adcp/types/generated_poc/core/assets/video_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/video_asset.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,17 +12,17 @@ class VideoAsset(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) bitrate_kbps: Annotated[ - int | None, Field(description="Video bitrate in kilobits per second", ge=1) + int | None, Field(description='Video bitrate in kilobits per second', ge=1) ] = None duration_ms: Annotated[ - int | None, Field(description="Video duration in milliseconds", ge=1) + int | None, Field(description='Video duration in milliseconds', ge=1) ] = None - format: Annotated[str | None, Field(description="Video file format (mp4, webm, mov, etc.)")] = ( + format: Annotated[str | None, Field(description='Video file format (mp4, webm, mov, etc.)')] = ( None ) - height: Annotated[int, Field(description="Height in pixels", ge=1)] - url: Annotated[AnyUrl, Field(description="URL to the video asset")] - width: Annotated[int, Field(description="Width in pixels", ge=1)] + height: Annotated[int, Field(description='Height in pixels', ge=1)] + url: Annotated[AnyUrl, Field(description='URL to the video asset')] + width: Annotated[int, Field(description='Width in pixels', ge=1)] diff --git a/src/adcp/types/generated_poc/core/assets/webhook_asset.py b/src/adcp/types/generated_poc/core/assets/webhook_asset.py index 8982990e..c8f875ae 100644 --- a/src/adcp/types/generated_poc/core/assets/webhook_asset.py +++ b/src/adcp/types/generated_poc/core/assets/webhook_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/webhook_asset.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -20,34 +20,34 @@ class Security(AdCPBaseModel): str | None, Field(description="Header name for HMAC signature (e.g., 'X-Signature')") ] = None method: Annotated[ - webhook_security_method.WebhookSecurityMethod, Field(description="Authentication method") + webhook_security_method.WebhookSecurityMethod, Field(description='Authentication method') ] class WebhookAsset(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - method: Annotated[http_method.HttpMethod | None, Field(description="HTTP method")] = ( + method: Annotated[http_method.HttpMethod | None, Field(description='HTTP method')] = ( http_method.HttpMethod.POST ) required_macros: Annotated[ list[str] | None, - Field(description="Universal macros that must be provided for webhook to function"), + Field(description='Universal macros that must be provided for webhook to function'), ] = None response_type: Annotated[ webhook_response_type.WebhookResponseType, - Field(description="Expected content type of webhook response"), + Field(description='Expected content type of webhook response'), ] - security: Annotated[Security, Field(description="Security configuration for webhook calls")] + security: Annotated[Security, Field(description='Security configuration for webhook calls')] supported_macros: Annotated[ list[str] | None, Field( - description="Universal macros that can be passed to webhook (e.g., {DEVICE_TYPE}, {COUNTRY})" + description='Universal macros that can be passed to webhook (e.g., {DEVICE_TYPE}, {COUNTRY})' ), ] = None timeout_ms: Annotated[ int | None, - Field(description="Maximum time to wait for response in milliseconds", ge=10, le=5000), + Field(description='Maximum time to wait for response in milliseconds', ge=10, le=5000), ] = 500 - url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] + url: Annotated[AnyUrl, Field(description='Webhook URL to call for dynamic content')] diff --git a/src/adcp/types/generated_poc/core/async_response_data.py b/src/adcp/types/generated_poc/core/async_response_data.py index fa25e6df..d9e7e989 100644 --- a/src/adcp/types/generated_poc/core/async_response_data.py +++ b/src/adcp/types/generated_poc/core/async_response_data.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/async_response_data.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -66,7 +66,7 @@ class AdcpAsyncResponseData( | sync_creatives_async_response_input_required.SyncCreativesInputRequired | sync_creatives_async_response_submitted.SyncCreativesSubmitted, Field( - description="Union of all possible data payloads for async task webhook responses. For completed/failed statuses, use the main task response schema. For working/input-required/submitted, use the status-specific schemas.", - title="AdCP Async Response Data", + description='Union of all possible data payloads for async task webhook responses. For completed/failed statuses, use the main task response schema. For working/input-required/submitted, use the status-specific schemas.', + title='AdCP Async Response Data', ), ] diff --git a/src/adcp/types/generated_poc/core/brand_manifest.py b/src/adcp/types/generated_poc/core/brand_manifest.py index 56d13b86..cb11918c 100644 --- a/src/adcp/types/generated_poc/core/brand_manifest.py +++ b/src/adcp/types/generated_poc/core/brand_manifest.py @@ -1,11 +1,11 @@ # generated by datamodel-codegen: # filename: core/brand_manifest.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations from enum import Enum -from typing import Annotated, Any +from typing import Annotated, Any, Literal from adcp.types.base import AdCPBaseModel from pydantic import AnyUrl, AwareDatetime, ConfigDict, EmailStr, Field @@ -15,61 +15,73 @@ class Asset(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - asset_id: Annotated[str, Field(description="Unique identifier for this asset")] + asset_id: Annotated[str, Field(description='Unique identifier for this asset')] asset_type: Annotated[ asset_content_type.AssetContentType, Field( - description="Type of asset. Note: Brand manifests typically contain basic media assets (image, video, audio, text). Code assets (html, javascript, css) and ad markup (vast, daast) are usually not part of brand asset libraries." + description='Type of asset. Note: Brand manifests typically contain basic media assets (image, video, audio, text). Code assets (html, javascript, css) and ad markup (vast, daast) are usually not part of brand asset libraries.' ), ] - description: Annotated[str | None, Field(description="Asset description or usage notes")] = None + description: Annotated[str | None, Field(description='Asset description or usage notes')] = None duration_seconds: Annotated[ - float | None, Field(description="Video/audio duration in seconds") + float | None, Field(description='Video/audio duration in seconds') ] = None - file_size_bytes: Annotated[int | None, Field(description="File size in bytes")] = None + file_size_bytes: Annotated[int | None, Field(description='File size in bytes')] = None format: Annotated[str | None, Field(description="File format (e.g., 'jpg', 'mp4', 'mp3')")] = ( None ) - height: Annotated[int | None, Field(description="Image/video height in pixels")] = None + height: Annotated[int | None, Field(description='Image/video height in pixels')] = None metadata: Annotated[ - dict[str, Any] | None, Field(description="Additional asset-specific metadata") + dict[str, Any] | None, Field(description='Additional asset-specific metadata') ] = None - name: Annotated[str | None, Field(description="Human-readable asset name")] = None + name: Annotated[str | None, Field(description='Human-readable asset name')] = None tags: Annotated[ list[str] | None, Field( description="Tags for asset discovery (e.g., 'holiday', 'lifestyle', 'product_shot')" ), ] = None - url: Annotated[AnyUrl, Field(description="URL to CDN-hosted asset file")] - width: Annotated[int | None, Field(description="Image/video width in pixels")] = None + url: Annotated[AnyUrl, Field(description='URL to CDN-hosted asset file')] + width: Annotated[int | None, Field(description='Image/video width in pixels')] = None + + +class Avatar(AdCPBaseModel): + avatar_id: Annotated[str | None, Field(description='Provider-specific avatar identifier')] = ( + None + ) + provider: Annotated[ + str | None, Field(description="Avatar provider (e.g., 'd-id', 'heygen', 'synthesia')") + ] = None + settings: Annotated[ + dict[str, Any] | None, Field(description='Provider-specific avatar settings') + ] = None class Colors(AdCPBaseModel): accent: Annotated[ - str | None, Field(description="Accent color (hex format)", pattern="^#[0-9A-Fa-f]{6}$") + str | None, Field(description='Accent color (hex format)', pattern='^#[0-9A-Fa-f]{6}$') ] = None background: Annotated[ - str | None, Field(description="Background color (hex format)", pattern="^#[0-9A-Fa-f]{6}$") + str | None, Field(description='Background color (hex format)', pattern='^#[0-9A-Fa-f]{6}$') ] = None primary: Annotated[ str | None, - Field(description="Primary brand color (hex format)", pattern="^#[0-9A-Fa-f]{6}$"), + Field(description='Primary brand color (hex format)', pattern='^#[0-9A-Fa-f]{6}$'), ] = None secondary: Annotated[ str | None, - Field(description="Secondary brand color (hex format)", pattern="^#[0-9A-Fa-f]{6}$"), + Field(description='Secondary brand color (hex format)', pattern='^#[0-9A-Fa-f]{6}$'), ] = None text: Annotated[ - str | None, Field(description="Text color (hex format)", pattern="^#[0-9A-Fa-f]{6}$") + str | None, Field(description='Text color (hex format)', pattern='^#[0-9A-Fa-f]{6}$') ] = None class Contact(AdCPBaseModel): - email: Annotated[EmailStr | None, Field(description="Contact email")] = None - phone: Annotated[str | None, Field(description="Contact phone number")] = None + email: Annotated[EmailStr | None, Field(description='Contact email')] = None + phone: Annotated[str | None, Field(description='Contact phone number')] = None class Disclaimer(AdCPBaseModel): @@ -79,92 +91,133 @@ class Disclaimer(AdCPBaseModel): description="When this disclaimer applies (e.g., 'financial_products', 'health_claims', 'all')" ), ] = None - required: Annotated[bool | None, Field(description="Whether this disclaimer must appear")] = ( + required: Annotated[bool | None, Field(description='Whether this disclaimer must appear')] = ( True ) - text: Annotated[str, Field(description="Disclaimer text")] + text: Annotated[str, Field(description='Disclaimer text')] class Fonts(AdCPBaseModel): font_urls: Annotated[ - list[AnyUrl] | None, Field(description="URLs to web font files if using custom fonts") + list[AnyUrl] | None, Field(description='URLs to web font files if using custom fonts') ] = None - primary: Annotated[str | None, Field(description="Primary font family name")] = None - secondary: Annotated[str | None, Field(description="Secondary font family name")] = None + primary: Annotated[str | None, Field(description='Primary font family name')] = None + secondary: Annotated[str | None, Field(description='Secondary font family name')] = None class Logo(AdCPBaseModel): - height: Annotated[int | None, Field(description="Logo height in pixels")] = None + height: Annotated[int | None, Field(description='Logo height in pixels')] = None tags: Annotated[ list[str] | None, Field( description="Semantic tags describing the logo variant (e.g., 'dark', 'light', 'square', 'horizontal', 'icon')" ), ] = None - url: Annotated[AnyUrl, Field(description="URL to the logo asset")] - width: Annotated[int | None, Field(description="Logo width in pixels")] = None + url: Annotated[AnyUrl, Field(description='URL to the logo asset')] + width: Annotated[int | None, Field(description='Logo width in pixels')] = None class Metadata(AdCPBaseModel): created_date: Annotated[ - AwareDatetime | None, Field(description="When this brand manifest was created") + AwareDatetime | None, Field(description='When this brand manifest was created') ] = None updated_date: Annotated[ - AwareDatetime | None, Field(description="When this brand manifest was last updated") + AwareDatetime | None, Field(description='When this brand manifest was last updated') + ] = None + version: Annotated[str | None, Field(description='Brand card version number')] = None + + +class AgenticCheckout(AdCPBaseModel): + endpoint: Annotated[ + AnyUrl, + Field( + description='Base URL for checkout session API (e.g., https://merchant.com/api/checkout_sessions)' + ), + ] + spec: Annotated[ + Literal['openai_agentic_checkout_v1'], + Field(description='Checkout API specification implemented by the endpoint'), + ] + supported_payment_providers: Annotated[ + list[str] | None, Field(description='Payment providers supported by this checkout endpoint') ] = None - version: Annotated[str | None, Field(description="Brand card version number")] = None class FeedFormat(Enum): - google_merchant_center = "google_merchant_center" - facebook_catalog = "facebook_catalog" - custom = "custom" + google_merchant_center = 'google_merchant_center' + facebook_catalog = 'facebook_catalog' + openai_product_feed = 'openai_product_feed' + custom = 'custom' class UpdateFrequency(Enum): - realtime = "realtime" - hourly = "hourly" - daily = "daily" - weekly = "weekly" + realtime = 'realtime' + hourly = 'hourly' + daily = 'daily' + weekly = 'weekly' class ProductCatalog(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) + agentic_checkout: Annotated[ + AgenticCheckout | None, + Field( + description='Agentic checkout endpoint configuration. Enables AI agents to complete purchases on behalf of users through a structured checkout API.' + ), + ] = None categories: Annotated[ list[str] | None, - Field(description="Product categories available in the catalog (for filtering)"), + Field(description='Product categories available in the catalog (for filtering)'), ] = None - feed_format: Annotated[FeedFormat | None, Field(description="Format of the product feed")] = ( - FeedFormat.google_merchant_center - ) - feed_url: Annotated[AnyUrl, Field(description="URL to product catalog feed")] + feed_format: Annotated[ + FeedFormat | None, + Field( + description="Format of the product feed. Use 'openai_product_feed' for feeds conforming to the OpenAI Commerce Product Feed specification." + ), + ] = FeedFormat.google_merchant_center + feed_url: Annotated[AnyUrl, Field(description='URL to product catalog feed')] last_updated: Annotated[ - AwareDatetime | None, Field(description="When the product catalog was last updated") + AwareDatetime | None, Field(description='When the product catalog was last updated') ] = None update_frequency: Annotated[ - UpdateFrequency | None, Field(description="How frequently the product catalog is updated") + UpdateFrequency | None, Field(description='How frequently the product catalog is updated') + ] = None + + +class Voice(AdCPBaseModel): + provider: Annotated[ + str | None, Field(description="TTS provider (e.g., 'elevenlabs', 'openai', 'amazon_polly')") ] = None + settings: Annotated[ + dict[str, Any] | None, + Field(description='Provider-specific voice settings (speed, pitch, etc.)'), + ] = None + voice_id: Annotated[str | None, Field(description='Provider-specific voice identifier')] = None class BrandManifest(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) assets: Annotated[ list[Asset] | None, Field( - description="Brand asset library with explicit assets and tags. Assets are referenced inline with URLs pointing to CDN-hosted files." + description='Brand asset library with explicit assets and tags. Assets are referenced inline with URLs pointing to CDN-hosted files.' ), ] = None - colors: Annotated[Colors | None, Field(description="Brand color palette")] = None - contact: Annotated[Contact | None, Field(description="Brand contact information")] = None + avatar: Annotated[ + Avatar | None, + Field(description='Brand avatar configuration for visual conversational experiences'), + ] = None + colors: Annotated[Colors | None, Field(description='Brand color palette')] = None + contact: Annotated[Contact | None, Field(description='Brand contact information')] = None disclaimers: Annotated[ list[Disclaimer] | None, - Field(description="Legal disclaimers or required text that must appear in creatives"), + Field(description='Legal disclaimers or required text that must appear in creatives'), ] = None - fonts: Annotated[Fonts | None, Field(description="Brand typography guidelines")] = None + fonts: Annotated[Fonts | None, Field(description='Brand typography guidelines')] = None industry: Annotated[ str | None, Field( @@ -173,19 +226,25 @@ class BrandManifest(AdCPBaseModel): ] = None logos: Annotated[ list[Logo] | None, - Field(description="Brand logo assets with semantic tags for different use cases"), + Field(description='Brand logo assets with semantic tags for different use cases'), + ] = None + metadata: Annotated[Metadata | None, Field(description='Additional brand metadata')] = None + name: Annotated[str, Field(description='Brand or business name')] + privacy_policy_url: Annotated[ + AnyUrl | None, + Field( + description="URL to the brand's privacy policy. Used for consumer consent flows when personal data may be shared with the advertiser. AI platforms can use this to present explicit privacy choices to users before data handoff." + ), ] = None - metadata: Annotated[Metadata | None, Field(description="Additional brand metadata")] = None - name: Annotated[str, Field(description="Brand or business name")] product_catalog: Annotated[ ProductCatalog | None, Field( - description="Product catalog information for e-commerce advertisers. Enables SKU-level creative generation and product selection." + description='Product catalog information for e-commerce advertisers. Enables SKU-level creative generation and product selection.' ), ] = None - tagline: Annotated[str | None, Field(description="Brand tagline or slogan")] = None + tagline: Annotated[str | None, Field(description='Brand tagline or slogan')] = None target_audience: Annotated[ - str | None, Field(description="Primary target audience description") + str | None, Field(description='Primary target audience description') ] = None tone: Annotated[ str | None, @@ -196,6 +255,10 @@ class BrandManifest(AdCPBaseModel): url: Annotated[ AnyUrl | None, Field( - description="Primary brand URL for context and asset discovery. Creative agents can infer brand information from this URL." + description='Primary brand URL for context and asset discovery. Creative agents can infer brand information from this URL.' ), ] = None + voice: Annotated[ + Voice | None, + Field(description='Brand voice configuration for audio/conversational experiences'), + ] = None diff --git a/src/adcp/types/generated_poc/core/brand_manifest_ref.py b/src/adcp/types/generated_poc/core/brand_manifest_ref.py index a1fb341a..bafda8db 100644 --- a/src/adcp/types/generated_poc/core/brand_manifest_ref.py +++ b/src/adcp/types/generated_poc/core/brand_manifest_ref.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/brand_manifest_ref.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,21 +15,21 @@ class BrandManifestReference(RootModel[brand_manifest.BrandManifest | AnyUrl]): root: Annotated[ brand_manifest.BrandManifest | AnyUrl, Field( - description="Brand manifest provided either as an inline object or a URL string pointing to a hosted manifest", + description='Brand manifest provided either as an inline object or a URL string pointing to a hosted manifest', examples=[ { - "data": { - "colors": {"primary": "#FF6B35"}, - "name": "ACME Corporation", - "url": "https://acmecorp.com", + 'data': { + 'colors': {'primary': '#FF6B35'}, + 'name': 'ACME Corporation', + 'url': 'https://acmecorp.com', }, - "description": "Inline brand manifest", + 'description': 'Inline brand manifest', }, { - "data": "https://cdn.acmecorp.com/brand-manifest.json", - "description": "URL string reference to hosted manifest", + 'data': 'https://cdn.acmecorp.com/brand-manifest.json', + 'description': 'URL string reference to hosted manifest', }, ], - title="Brand Manifest Reference", + title='Brand Manifest Reference', ), ] diff --git a/src/adcp/types/generated_poc/core/context.py b/src/adcp/types/generated_poc/core/context.py index a331704d..1c153192 100644 --- a/src/adcp/types/generated_poc/core/context.py +++ b/src/adcp/types/generated_poc/core/context.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/context.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -10,5 +10,5 @@ class ContextObject(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) diff --git a/src/adcp/types/generated_poc/core/creative_asset.py b/src/adcp/types/generated_poc/core/creative_asset.py index 7575148d..b8ede7e8 100644 --- a/src/adcp/types/generated_poc/core/creative_asset.py +++ b/src/adcp/types/generated_poc/core/creative_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_asset.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -9,6 +9,7 @@ from adcp.types.base import AdCPBaseModel from pydantic import ConfigDict, Field +from ..enums import creative_status from . import format_id as format_id_1 from . import promoted_offerings from .assets import ( @@ -27,28 +28,22 @@ class Input(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context_description: Annotated[ str | None, - Field(description="Natural language description of the context for AI-generated content"), + Field(description='Natural language description of the context for AI-generated content'), ] = None macros: Annotated[ - dict[str, str] | None, Field(description="Macro values to apply for this preview") + dict[str, str] | None, Field(description='Macro values to apply for this preview') ] = None - name: Annotated[str, Field(description="Human-readable name for this preview variant")] + name: Annotated[str, Field(description='Human-readable name for this preview variant')] class CreativeAsset(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - approved: Annotated[ - bool | None, - Field( - description="For generative creatives: set to true to approve and finalize, false to request regeneration with updated assets/message. Omit for non-generative creatives." - ), - ] = None assets: Annotated[ dict[ str, @@ -64,22 +59,22 @@ class CreativeAsset(AdCPBaseModel): | promoted_offerings.PromotedOfferings | url_asset.UrlAsset, ], - Field(description="Assets required by the format, keyed by asset_role"), + Field(description='Assets required by the format, keyed by asset_role'), ] - creative_id: Annotated[str, Field(description="Unique identifier for the creative")] + creative_id: Annotated[str, Field(description='Unique identifier for the creative')] format_id: Annotated[ format_id_1.FormatId, Field( - description="Format identifier specifying which format this creative conforms to. Can be: (1) concrete format_id referencing a format with fixed dimensions, (2) template format_id referencing a template format, or (3) parameterized format_id with dimensions/duration parameters for template formats." + description='Format identifier specifying which format this creative conforms to. Can be: (1) concrete format_id referencing a format with fixed dimensions, (2) template format_id referencing a template format, or (3) parameterized format_id with dimensions/duration parameters for template formats.' ), ] inputs: Annotated[ list[Input] | None, Field( - description="Preview contexts for generative formats - defines what scenarios to generate previews for" + description='Preview contexts for generative formats - defines what scenarios to generate previews for' ), ] = None - name: Annotated[str, Field(description="Human-readable creative name")] + name: Annotated[str, Field(description='Human-readable creative name')] placement_ids: Annotated[ list[str] | None, Field( @@ -87,13 +82,19 @@ class CreativeAsset(AdCPBaseModel): min_length=1, ), ] = None + status: Annotated[ + creative_status.CreativeStatus | None, + Field( + description="For generative creatives: set to 'approved' to finalize, 'rejected' to request regeneration with updated assets/message. Omit for non-generative creatives (system will set based on processing state)." + ), + ] = None tags: Annotated[ - list[str] | None, Field(description="User-defined tags for organization and searchability") + list[str] | None, Field(description='User-defined tags for organization and searchability') ] = None weight: Annotated[ float | None, Field( - description="Optional delivery weight for creative rotation when uploading via create_media_buy or update_media_buy (0-100). If omitted, platform determines rotation. Only used during upload to media buy - not stored in creative library.", + description='Optional delivery weight for creative rotation when uploading via create_media_buy or update_media_buy (0-100). If omitted, platform determines rotation. Only used during upload to media buy - not stored in creative library.', ge=0.0, le=100.0, ), diff --git a/src/adcp/types/generated_poc/core/creative_assignment.py b/src/adcp/types/generated_poc/core/creative_assignment.py index c8fd8338..1f73fefc 100644 --- a/src/adcp/types/generated_poc/core/creative_assignment.py +++ b/src/adcp/types/generated_poc/core/creative_assignment.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_assignment.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,9 +12,9 @@ class CreativeAssignment(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - creative_id: Annotated[str, Field(description="Unique identifier for the creative")] + creative_id: Annotated[str, Field(description='Unique identifier for the creative')] placement_ids: Annotated[ list[str] | None, Field( @@ -23,5 +23,5 @@ class CreativeAssignment(AdCPBaseModel): ), ] = None weight: Annotated[ - float | None, Field(description="Delivery weight for this creative", ge=0.0, le=100.0) + float | None, Field(description='Delivery weight for this creative', ge=0.0, le=100.0) ] = None diff --git a/src/adcp/types/generated_poc/core/creative_filters.py b/src/adcp/types/generated_poc/core/creative_filters.py index ba09200f..daab7bf1 100644 --- a/src/adcp/types/generated_poc/core/creative_filters.py +++ b/src/adcp/types/generated_poc/core/creative_filters.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_filters.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,73 +14,63 @@ class CreativeFilters(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - assigned_to_package: Annotated[ - str | None, Field(description="Filter creatives assigned to this specific package") - ] = None assigned_to_packages: Annotated[ - list[str] | None, Field(description="Filter creatives assigned to any of these packages") + list[str] | None, Field(description='Filter creatives assigned to any of these packages') ] = None buyer_refs: Annotated[ list[str] | None, Field( - description="Filter creatives assigned to media buys with any of these buyer references" + description='Filter creatives assigned to media buys with any of these buyer references' ), ] = None created_after: Annotated[ AwareDatetime | None, - Field(description="Filter creatives created after this date (ISO 8601)"), + Field(description='Filter creatives created after this date (ISO 8601)'), ] = None created_before: Annotated[ AwareDatetime | None, - Field(description="Filter creatives created before this date (ISO 8601)"), + Field(description='Filter creatives created before this date (ISO 8601)'), ] = None creative_ids: Annotated[ - list[str] | None, Field(description="Filter by specific creative IDs", max_length=100) - ] = None - format: Annotated[ - str | None, - Field(description="Filter by creative format type (e.g., video, audio, display)"), + list[str] | None, Field(description='Filter by specific creative IDs', max_length=100) ] = None formats: Annotated[ - list[str] | None, Field(description="Filter by multiple creative format types") + list[str] | None, + Field(description='Filter by creative format types (e.g., video, audio, display)'), ] = None has_performance_data: Annotated[ - bool | None, Field(description="Filter creatives that have performance data when true") + bool | None, Field(description='Filter creatives that have performance data when true') ] = None media_buy_ids: Annotated[ - list[str] | None, Field(description="Filter creatives assigned to any of these media buys") + list[str] | None, Field(description='Filter creatives assigned to any of these media buys') ] = None name_contains: Annotated[ str | None, - Field(description="Filter by creative names containing this text (case-insensitive)"), - ] = None - status: Annotated[ - creative_status.CreativeStatus | None, - Field(description="Filter by creative approval status"), + Field(description='Filter by creative names containing this text (case-insensitive)'), ] = None statuses: Annotated[ list[creative_status.CreativeStatus] | None, - Field(description="Filter by multiple creative statuses"), + Field(description='Filter by creative approval statuses'), ] = None tags: Annotated[ - list[str] | None, Field(description="Filter by creative tags (all tags must match)") + list[str] | None, Field(description='Filter by creative tags (all tags must match)') ] = None tags_any: Annotated[ - list[str] | None, Field(description="Filter by creative tags (any tag must match)") + list[str] | None, Field(description='Filter by creative tags (any tag must match)') ] = None unassigned: Annotated[ bool | None, Field( - description="Filter for unassigned creatives when true, assigned creatives when false" + description='Filter for unassigned creatives when true, assigned creatives when false' ), ] = None updated_after: Annotated[ AwareDatetime | None, - Field(description="Filter creatives last updated after this date (ISO 8601)"), + Field(description='Filter creatives last updated after this date (ISO 8601)'), ] = None updated_before: Annotated[ AwareDatetime | None, - Field(description="Filter creatives last updated before this date (ISO 8601)"), + Field(description='Filter creatives last updated before this date (ISO 8601)'), ] = None diff --git a/src/adcp/types/generated_poc/core/creative_manifest.py b/src/adcp/types/generated_poc/core/creative_manifest.py index de1865b9..62632cc1 100644 --- a/src/adcp/types/generated_poc/core/creative_manifest.py +++ b/src/adcp/types/generated_poc/core/creative_manifest.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_manifest.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -29,7 +29,7 @@ class CreativeManifest(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) assets: Annotated[ dict[ @@ -61,6 +61,6 @@ class CreativeManifest(AdCPBaseModel): promoted_offering: Annotated[ str | None, Field( - description="Product name or offering being advertised. Maps to promoted_offerings in create_media_buy request to associate creative with the product being promoted." + description='Product name or offering being advertised. Maps to promoted_offerings in create_media_buy request to associate creative with the product being promoted.' ), ] = None diff --git a/src/adcp/types/generated_poc/core/creative_policy.py b/src/adcp/types/generated_poc/core/creative_policy.py index 6126fbc3..f6f06ff5 100644 --- a/src/adcp/types/generated_poc/core/creative_policy.py +++ b/src/adcp/types/generated_poc/core/creative_policy.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_policy.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,15 +14,15 @@ class CreativePolicy(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) co_branding: Annotated[ - co_branding_requirement.CoBrandingRequirement, Field(description="Co-branding requirement") + co_branding_requirement.CoBrandingRequirement, Field(description='Co-branding requirement') ] landing_page: Annotated[ landing_page_requirement.LandingPageRequirement, - Field(description="Landing page requirements"), + Field(description='Landing page requirements'), ] templates_available: Annotated[ - bool, Field(description="Whether creative templates are provided") + bool, Field(description='Whether creative templates are provided') ] diff --git a/src/adcp/types/generated_poc/core/delivery_metrics.py b/src/adcp/types/generated_poc/core/delivery_metrics.py index 888dd7e8..dd528f13 100644 --- a/src/adcp/types/generated_poc/core/delivery_metrics.py +++ b/src/adcp/types/generated_poc/core/delivery_metrics.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/delivery_metrics.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,15 +12,15 @@ class VenueBreakdownItem(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - impressions: Annotated[int, Field(description="Impressions delivered at this venue", ge=0)] - loop_plays: Annotated[int | None, Field(description="Loop plays at this venue", ge=0)] = None + impressions: Annotated[int, Field(description='Impressions delivered at this venue', ge=0)] + loop_plays: Annotated[int | None, Field(description='Loop plays at this venue', ge=0)] = None screens_used: Annotated[ - int | None, Field(description="Number of screens used at this venue", ge=0) + int | None, Field(description='Number of screens used at this venue', ge=0) ] = None - venue_id: Annotated[str, Field(description="Venue identifier")] - venue_name: Annotated[str | None, Field(description="Human-readable venue name")] = None + venue_id: Annotated[str, Field(description='Venue identifier')] + venue_name: Annotated[str | None, Field(description='Human-readable venue name')] = None venue_type: Annotated[ str | None, Field(description="Venue type (e.g., 'airport', 'transit', 'retail', 'billboard')"), @@ -29,83 +29,83 @@ class VenueBreakdownItem(AdCPBaseModel): class DoohMetrics(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) calculation_notes: Annotated[ - str | None, Field(description="Explanation of how DOOH impressions were calculated") + str | None, Field(description='Explanation of how DOOH impressions were calculated') ] = None loop_plays: Annotated[ - int | None, Field(description="Number of times ad played in rotation", ge=0) + int | None, Field(description='Number of times ad played in rotation', ge=0) ] = None screen_time_seconds: Annotated[ - int | None, Field(description="Total display time in seconds", ge=0) + int | None, Field(description='Total display time in seconds', ge=0) ] = None screens_used: Annotated[ - int | None, Field(description="Number of unique screens displaying the ad", ge=0) + int | None, Field(description='Number of unique screens displaying the ad', ge=0) ] = None sov_achieved: Annotated[ float | None, - Field(description="Actual share of voice delivered (0.0 to 1.0)", ge=0.0, le=1.0), + Field(description='Actual share of voice delivered (0.0 to 1.0)', ge=0.0, le=1.0), ] = None venue_breakdown: Annotated[ - list[VenueBreakdownItem] | None, Field(description="Per-venue performance breakdown") + list[VenueBreakdownItem] | None, Field(description='Per-venue performance breakdown') ] = None class QuartileData(AdCPBaseModel): - q1_views: Annotated[float | None, Field(description="25% completion views", ge=0.0)] = None - q2_views: Annotated[float | None, Field(description="50% completion views", ge=0.0)] = None - q3_views: Annotated[float | None, Field(description="75% completion views", ge=0.0)] = None - q4_views: Annotated[float | None, Field(description="100% completion views", ge=0.0)] = None + q1_views: Annotated[float | None, Field(description='25% completion views', ge=0.0)] = None + q2_views: Annotated[float | None, Field(description='50% completion views', ge=0.0)] = None + q3_views: Annotated[float | None, Field(description='75% completion views', ge=0.0)] = None + q4_views: Annotated[float | None, Field(description='100% completion views', ge=0.0)] = None class DeliveryMetrics(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - clicks: Annotated[float | None, Field(description="Total clicks", ge=0.0)] = None + clicks: Annotated[float | None, Field(description='Total clicks', ge=0.0)] = None completed_views: Annotated[ - float | None, Field(description="100% completions (for CPCV)", ge=0.0) + float | None, Field(description='100% completions (for CPCV)', ge=0.0) ] = None completion_rate: Annotated[ float | None, - Field(description="Completion rate (completed_views/impressions)", ge=0.0, le=1.0), + Field(description='Completion rate (completed_views/impressions)', ge=0.0, le=1.0), ] = None conversions: Annotated[ float | None, - Field(description="Conversions (reserved for future CPA pricing support)", ge=0.0), + Field(description='Conversions (reserved for future CPA pricing support)', ge=0.0), ] = None ctr: Annotated[ - float | None, Field(description="Click-through rate (clicks/impressions)", ge=0.0, le=1.0) + float | None, Field(description='Click-through rate (clicks/impressions)', ge=0.0, le=1.0) ] = None dooh_metrics: Annotated[ DoohMetrics | None, - Field(description="DOOH-specific metrics (only included for DOOH campaigns)"), + Field(description='DOOH-specific metrics (only included for DOOH campaigns)'), ] = None frequency: Annotated[ float | None, Field( - description="Average frequency per individual (typically measured over campaign duration, but can vary by measurement provider)", + description='Average frequency per individual (typically measured over campaign duration, but can vary by measurement provider)', ge=0.0, ), ] = None grps: Annotated[ - float | None, Field(description="Gross Rating Points delivered (for CPP)", ge=0.0) + float | None, Field(description='Gross Rating Points delivered (for CPP)', ge=0.0) ] = None - impressions: Annotated[float | None, Field(description="Impressions delivered", ge=0.0)] = None + impressions: Annotated[float | None, Field(description='Impressions delivered', ge=0.0)] = None leads: Annotated[ float | None, - Field(description="Leads generated (reserved for future CPL pricing support)", ge=0.0), + Field(description='Leads generated (reserved for future CPL pricing support)', ge=0.0), ] = None quartile_data: Annotated[ - QuartileData | None, Field(description="Video quartile completion data") + QuartileData | None, Field(description='Video quartile completion data') ] = None reach: Annotated[ float | None, Field( - description="Unique reach - units depend on measurement provider (e.g., individuals, households, devices, cookies). See delivery_measurement.provider for methodology.", + description='Unique reach - units depend on measurement provider (e.g., individuals, households, devices, cookies). See delivery_measurement.provider for methodology.', ge=0.0, ), ] = None - spend: Annotated[float | None, Field(description="Amount spent", ge=0.0)] = None - views: Annotated[float | None, Field(description="Views at threshold (for CPV)", ge=0.0)] = None + spend: Annotated[float | None, Field(description='Amount spent', ge=0.0)] = None + views: Annotated[float | None, Field(description='Views at threshold (for CPV)', ge=0.0)] = None diff --git a/src/adcp/types/generated_poc/core/deployment.py b/src/adcp/types/generated_poc/core/deployment.py index 2c4bd806..4568134c 100644 --- a/src/adcp/types/generated_poc/core/deployment.py +++ b/src/adcp/types/generated_poc/core/deployment.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/deployment.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,65 +14,65 @@ class Deployment1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - account: Annotated[str | None, Field(description="Account identifier if applicable")] = None + account: Annotated[str | None, Field(description='Account identifier if applicable')] = None activation_key: Annotated[ activation_key_1.ActivationKey | None, Field( - description="The key to use for targeting. Only present if is_live=true AND requester has access to this deployment." + description='The key to use for targeting. Only present if is_live=true AND requester has access to this deployment.' ), ] = None deployed_at: Annotated[ AwareDatetime | None, - Field(description="Timestamp when activation completed (if is_live=true)"), + Field(description='Timestamp when activation completed (if is_live=true)'), ] = None estimated_activation_duration_minutes: Annotated[ float | None, Field( - description="Estimated time to activate if not live, or to complete activation if in progress", + description='Estimated time to activate if not live, or to complete activation if in progress', ge=0.0, ), ] = None is_live: Annotated[ - bool, Field(description="Whether signal is currently active on this deployment") + bool, Field(description='Whether signal is currently active on this deployment') ] - platform: Annotated[str, Field(description="Platform identifier for DSPs")] + platform: Annotated[str, Field(description='Platform identifier for DSPs')] type: Annotated[ - Literal["platform"], - Field(description="Discriminator indicating this is a platform-based deployment"), + Literal['platform'], + Field(description='Discriminator indicating this is a platform-based deployment'), ] class Deployment2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - account: Annotated[str | None, Field(description="Account identifier if applicable")] = None + account: Annotated[str | None, Field(description='Account identifier if applicable')] = None activation_key: Annotated[ activation_key_1.ActivationKey | None, Field( - description="The key to use for targeting. Only present if is_live=true AND requester has access to this deployment." + description='The key to use for targeting. Only present if is_live=true AND requester has access to this deployment.' ), ] = None - agent_url: Annotated[AnyUrl, Field(description="URL identifying the deployment agent")] + agent_url: Annotated[AnyUrl, Field(description='URL identifying the deployment agent')] deployed_at: Annotated[ AwareDatetime | None, - Field(description="Timestamp when activation completed (if is_live=true)"), + Field(description='Timestamp when activation completed (if is_live=true)'), ] = None estimated_activation_duration_minutes: Annotated[ float | None, Field( - description="Estimated time to activate if not live, or to complete activation if in progress", + description='Estimated time to activate if not live, or to complete activation if in progress', ge=0.0, ), ] = None is_live: Annotated[ - bool, Field(description="Whether signal is currently active on this deployment") + bool, Field(description='Whether signal is currently active on this deployment') ] type: Annotated[ - Literal["agent"], - Field(description="Discriminator indicating this is an agent URL-based deployment"), + Literal['agent'], + Field(description='Discriminator indicating this is an agent URL-based deployment'), ] @@ -80,7 +80,7 @@ class Deployment(RootModel[Deployment1 | Deployment2]): root: Annotated[ Deployment1 | Deployment2, Field( - description="A signal deployment to a specific deployment target with activation status and key", - title="Deployment", + description='A signal deployment to a specific deployment target with activation status and key', + title='Deployment', ), ] diff --git a/src/adcp/types/generated_poc/core/destination.py b/src/adcp/types/generated_poc/core/destination.py index ee52b210..0aa6f861 100644 --- a/src/adcp/types/generated_poc/core/destination.py +++ b/src/adcp/types/generated_poc/core/destination.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/destination.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,34 +12,34 @@ class Destination1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) account: Annotated[ - str | None, Field(description="Optional account identifier on the platform") + str | None, Field(description='Optional account identifier on the platform') ] = None platform: Annotated[ str, Field(description="Platform identifier for DSPs (e.g., 'the-trade-desk', 'amazon-dsp')"), ] type: Annotated[ - Literal["platform"], - Field(description="Discriminator indicating this is a platform-based deployment"), + Literal['platform'], + Field(description='Discriminator indicating this is a platform-based deployment'), ] class Destination2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) account: Annotated[ - str | None, Field(description="Optional account identifier on the agent") + str | None, Field(description='Optional account identifier on the agent') ] = None agent_url: Annotated[ - AnyUrl, Field(description="URL identifying the deployment agent (for sales agents, etc.)") + AnyUrl, Field(description='URL identifying the deployment agent (for sales agents, etc.)') ] type: Annotated[ - Literal["agent"], - Field(description="Discriminator indicating this is an agent URL-based deployment"), + Literal['agent'], + Field(description='Discriminator indicating this is an agent URL-based deployment'), ] @@ -47,7 +47,7 @@ class Destination(RootModel[Destination1 | Destination2]): root: Annotated[ Destination1 | Destination2, Field( - description="A deployment target where signals can be activated (DSP, sales agent, etc.)", - title="Destination", + description='A deployment target where signals can be activated (DSP, sales agent, etc.)', + title='Destination', ), ] diff --git a/src/adcp/types/generated_poc/core/error.py b/src/adcp/types/generated_poc/core/error.py index 134e5683..912a913a 100644 --- a/src/adcp/types/generated_poc/core/error.py +++ b/src/adcp/types/generated_poc/core/error.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/error.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,18 +12,18 @@ class Error(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - code: Annotated[str, Field(description="Error code for programmatic handling")] + code: Annotated[str, Field(description='Error code for programmatic handling')] details: Annotated[ - dict[str, Any] | None, Field(description="Additional task-specific error details") + dict[str, Any] | None, Field(description='Additional task-specific error details') ] = None field: Annotated[ str | None, Field(description="Field path associated with the error (e.g., 'packages[0].targeting')"), ] = None - message: Annotated[str, Field(description="Human-readable error message")] + message: Annotated[str, Field(description='Human-readable error message')] retry_after: Annotated[ - float | None, Field(description="Seconds to wait before retrying the operation", ge=0.0) + float | None, Field(description='Seconds to wait before retrying the operation', ge=0.0) ] = None - suggestion: Annotated[str | None, Field(description="Suggested fix for the error")] = None + suggestion: Annotated[str | None, Field(description='Suggested fix for the error')] = None diff --git a/src/adcp/types/generated_poc/core/ext.py b/src/adcp/types/generated_poc/core/ext.py index 62607673..b3d633d0 100644 --- a/src/adcp/types/generated_poc/core/ext.py +++ b/src/adcp/types/generated_poc/core/ext.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/ext.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -10,5 +10,5 @@ class ExtensionObject(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) diff --git a/src/adcp/types/generated_poc/core/format.py b/src/adcp/types/generated_poc/core/format.py index 078aec0e..7439a669 100644 --- a/src/adcp/types/generated_poc/core/format.py +++ b/src/adcp/types/generated_poc/core/format.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/format.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class Assets(AdCPBaseModel): asset_id: Annotated[ str, Field( - description="Unique identifier for this asset. Creative manifests MUST use this exact value as the key in the assets object." + description='Unique identifier for this asset. Creative manifests MUST use this exact value as the key in the assets object.' ), ] asset_role: Annotated[ @@ -26,67 +26,67 @@ class Assets(AdCPBaseModel): description="Optional descriptive label for this asset's purpose (e.g., 'hero_image', 'logo', 'third_party_tracking'). Not used for referencing assets in manifests—use asset_id instead. This field is for human-readable documentation and UI display only." ), ] = None - asset_type: Annotated[asset_content_type.AssetContentType, Field(description="Type of asset")] + asset_type: Annotated[asset_content_type.AssetContentType, Field(description='Type of asset')] item_type: Annotated[ - Literal["individual"], - Field(description="Discriminator indicating this is an individual asset"), + Literal['individual'], + Field(description='Discriminator indicating this is an individual asset'), ] required: Annotated[ bool, Field( - description="Whether this asset is required (true) or optional (false). Required assets must be provided for a valid creative. Optional assets enhance the creative but are not mandatory." + description='Whether this asset is required (true) or optional (false). Required assets must be provided for a valid creative. Optional assets enhance the creative but are not mandatory.' ), ] requirements: Annotated[ dict[str, Any] | None, Field( - description="Technical requirements for this asset (dimensions, file size, duration, etc.). For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms)." + description='Technical requirements for this asset (dimensions, file size, duration, etc.). For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms).' ), ] = None class Asset(AdCPBaseModel): - asset_id: Annotated[str, Field(description="Identifier for this asset within the group")] + asset_id: Annotated[str, Field(description='Identifier for this asset within the group')] asset_role: Annotated[ str | None, Field( description="Optional descriptive label for this asset's purpose. Not used for referencing assets in manifests—use asset_id instead. This field is for human-readable documentation and UI display only." ), ] = None - asset_type: Annotated[asset_content_type.AssetContentType, Field(description="Type of asset")] + asset_type: Annotated[asset_content_type.AssetContentType, Field(description='Type of asset')] required: Annotated[ bool, - Field(description="Whether this asset is required within each repetition of the group"), + Field(description='Whether this asset is required within each repetition of the group'), ] requirements: Annotated[ dict[str, Any] | None, Field( - description="Technical requirements for this asset. For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms)." + description='Technical requirements for this asset. For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms).' ), ] = None -class Assets1(AdCPBaseModel): +class Assets5(AdCPBaseModel): asset_group_id: Annotated[ str, Field(description="Identifier for this asset group (e.g., 'product', 'slide', 'card')") ] - assets: Annotated[list[Asset], Field(description="Assets within each repetition of this group")] + assets: Annotated[list[Asset], Field(description='Assets within each repetition of this group')] item_type: Annotated[ - Literal["repeatable_group"], - Field(description="Discriminator indicating this is a repeatable asset group"), + Literal['repeatable_group'], + Field(description='Discriminator indicating this is a repeatable asset group'), ] - max_count: Annotated[int, Field(description="Maximum number of repetitions allowed", ge=1)] + max_count: Annotated[int, Field(description='Maximum number of repetitions allowed', ge=1)] min_count: Annotated[ int, Field( - description="Minimum number of repetitions required (if group is required) or allowed (if optional)", + description='Minimum number of repetitions required (if group is required) or allowed (if optional)', ge=0, ), ] required: Annotated[ bool, Field( - description="Whether this asset group is required. If true, at least min_count repetitions must be provided." + description='Whether this asset group is required. If true, at least min_count repetitions must be provided.' ), ] @@ -95,7 +95,7 @@ class AssetsRequired(AdCPBaseModel): asset_id: Annotated[ str, Field( - description="Unique identifier for this asset. Creative manifests MUST use this exact value as the key in the assets object." + description='Unique identifier for this asset. Creative manifests MUST use this exact value as the key in the assets object.' ), ] asset_role: Annotated[ @@ -104,36 +104,36 @@ class AssetsRequired(AdCPBaseModel): description="Optional descriptive label for this asset's purpose (e.g., 'hero_image', 'logo'). Not used for referencing assets in manifests—use asset_id instead. This field is for human-readable documentation and UI display only." ), ] = None - asset_type: Annotated[asset_content_type.AssetContentType, Field(description="Type of asset")] + asset_type: Annotated[asset_content_type.AssetContentType, Field(description='Type of asset')] item_type: Annotated[ - Literal["individual"], - Field(description="Discriminator indicating this is an individual asset requirement"), + Literal['individual'], + Field(description='Discriminator indicating this is an individual asset requirement'), ] - required: Annotated[bool | None, Field(description="Whether this asset is required")] = None + required: Annotated[bool | None, Field(description='Whether this asset is required')] = None requirements: Annotated[ dict[str, Any] | None, Field( - description="Technical requirements for this asset (dimensions, file size, duration, etc.). For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms)." + description='Technical requirements for this asset (dimensions, file size, duration, etc.). For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms).' ), ] = None class Asset2(AdCPBaseModel): - asset_id: Annotated[str, Field(description="Identifier for this asset within the group")] + asset_id: Annotated[str, Field(description='Identifier for this asset within the group')] asset_role: Annotated[ str | None, Field( description="Optional descriptive label for this asset's purpose (e.g., 'hero_image', 'logo'). Not used for referencing assets in manifests—use asset_id instead. This field is for human-readable documentation and UI display only." ), ] = None - asset_type: Annotated[asset_content_type.AssetContentType, Field(description="Type of asset")] + asset_type: Annotated[asset_content_type.AssetContentType, Field(description='Type of asset')] required: Annotated[ - bool | None, Field(description="Whether this asset is required in each repetition") + bool | None, Field(description='Whether this asset is required in each repetition') ] = None requirements: Annotated[ dict[str, Any] | None, Field( - description="Technical requirements for this asset. For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms)." + description='Technical requirements for this asset. For template formats, use parameters_from_format_id: true to indicate asset parameters must match the format_id parameters (width/height/unit and/or duration_ms).' ), ] = None @@ -143,14 +143,14 @@ class AssetsRequired1(AdCPBaseModel): str, Field(description="Identifier for this asset group (e.g., 'product', 'slide', 'card')") ] assets: Annotated[ - list[Asset2], Field(description="Assets within each repetition of this group") + list[Asset2], Field(description='Assets within each repetition of this group') ] item_type: Annotated[ - Literal["repeatable_group"], - Field(description="Discriminator indicating this is a repeatable asset group"), + Literal['repeatable_group'], + Field(description='Discriminator indicating this is a repeatable asset group'), ] - max_count: Annotated[int, Field(description="Maximum number of repetitions allowed", ge=1)] - min_count: Annotated[int, Field(description="Minimum number of repetitions required", ge=1)] + max_count: Annotated[int, Field(description='Maximum number of repetitions allowed', ge=1)] + min_count: Annotated[int, Field(description='Minimum number of repetitions required', ge=1)] class Responsive(AdCPBaseModel): @@ -163,36 +163,36 @@ class Dimensions(AdCPBaseModel): str | None, Field( description="Fixed aspect ratio constraint (e.g., '16:9', '4:3', '1:1')", - pattern="^\\d+:\\d+$", + pattern='^\\d+:\\d+$', ), ] = None - height: Annotated[int | None, Field(description="Fixed height in pixels", ge=1)] = None + height: Annotated[int | None, Field(description='Fixed height in pixels', ge=1)] = None max_height: Annotated[ - int | None, Field(description="Maximum height in pixels for responsive renders", ge=1) + int | None, Field(description='Maximum height in pixels for responsive renders', ge=1) ] = None max_width: Annotated[ - int | None, Field(description="Maximum width in pixels for responsive renders", ge=1) + int | None, Field(description='Maximum width in pixels for responsive renders', ge=1) ] = None min_height: Annotated[ - int | None, Field(description="Minimum height in pixels for responsive renders", ge=1) + int | None, Field(description='Minimum height in pixels for responsive renders', ge=1) ] = None min_width: Annotated[ - int | None, Field(description="Minimum width in pixels for responsive renders", ge=1) + int | None, Field(description='Minimum width in pixels for responsive renders', ge=1) ] = None responsive: Annotated[ - Responsive | None, Field(description="Indicates which dimensions are responsive/fluid") + Responsive | None, Field(description='Indicates which dimensions are responsive/fluid') ] = None - width: Annotated[int | None, Field(description="Fixed width in pixels", ge=1)] = None + width: Annotated[int | None, Field(description='Fixed width in pixels', ge=1)] = None class Renders(AdCPBaseModel): dimensions: Annotated[ - Dimensions, Field(description="Dimensions for this rendered piece (in pixels)") + Dimensions, Field(description='Dimensions for this rendered piece (in pixels)') ] parameters_from_format_id: Annotated[ bool | None, Field( - description="When true, parameters for this render (dimensions and/or duration) are specified in the format_id. Used for template formats that accept parameters. Mutually exclusive with specifying dimensions object explicitly." + description='When true, parameters for this render (dimensions and/or duration) are specified in the format_id. Used for template formats that accept parameters. Mutually exclusive with specifying dimensions object explicitly.' ), ] = None role: Annotated[ @@ -209,12 +209,12 @@ class Dimensions1(Dimensions): class Renders1(AdCPBaseModel): dimensions: Annotated[ - Dimensions1 | None, Field(description="Dimensions for this rendered piece (in pixels)") + Dimensions1 | None, Field(description='Dimensions for this rendered piece (in pixels)') ] = None parameters_from_format_id: Annotated[ Literal[True], Field( - description="When true, parameters for this render (dimensions and/or duration) are specified in the format_id. Used for template formats that accept parameters. Mutually exclusive with specifying dimensions object explicitly." + description='When true, parameters for this render (dimensions and/or duration) are specified in the format_id. Used for template formats that accept parameters. Mutually exclusive with specifying dimensions object explicitly.' ), ] role: Annotated[ @@ -227,50 +227,50 @@ class Renders1(AdCPBaseModel): class FormatCard(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) format_id: Annotated[ format_id_1.FormatId, Field( - description="Creative format defining the card layout (typically format_card_standard)" + description='Creative format defining the card layout (typically format_card_standard)' ), ] manifest: Annotated[ dict[str, Any], - Field(description="Asset manifest for rendering the card, structure defined by the format"), + Field(description='Asset manifest for rendering the card, structure defined by the format'), ] class FormatCardDetailed(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) format_id: Annotated[ format_id_1.FormatId, Field( - description="Creative format defining the detailed card layout (typically format_card_detailed)" + description='Creative format defining the detailed card layout (typically format_card_detailed)' ), ] manifest: Annotated[ dict[str, Any], Field( - description="Asset manifest for rendering the detailed card, structure defined by the format" + description='Asset manifest for rendering the detailed card, structure defined by the format' ), ] class Format(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) accepts_parameters: Annotated[ list[format_id_parameter.FormatIdParameter] | None, Field( - description="List of parameters this format accepts in format_id. Template formats define which parameters (dimensions, duration, etc.) can be specified when instantiating the format. Empty or omitted means this is a concrete format with fixed parameters." + description='List of parameters this format accepts in format_id. Template formats define which parameters (dimensions, duration, etc.) can be specified when instantiating the format. Empty or omitted means this is a concrete format with fixed parameters.' ), ] = None assets: Annotated[ - list[Assets | Assets1] | None, + list[Assets | Assets5] | None, Field( description="Array of all assets supported for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Use the 'required' boolean on each asset to indicate whether it's mandatory. This field replaces the deprecated 'assets_required' and enables full asset discovery for buyers and AI agents." ), @@ -284,65 +284,65 @@ class Format(AdCPBaseModel): ] = None delivery: Annotated[ dict[str, Any] | None, - Field(description="Delivery method specifications (e.g., hosted, VAST, third-party tags)"), + Field(description='Delivery method specifications (e.g., hosted, VAST, third-party tags)'), ] = None description: Annotated[ str | None, Field( - description="Plain text explanation of what this format does and what assets it requires" + description='Plain text explanation of what this format does and what assets it requires' ), ] = None example_url: Annotated[ AnyUrl | None, Field( - description="Optional URL to showcase page with examples and interactive demos of this format" + description='Optional URL to showcase page with examples and interactive demos of this format' ), ] = None format_card: Annotated[ FormatCard | None, Field( - description="Optional standard visual card (300x400px) for displaying this format in user interfaces. Can be rendered via preview_creative or pre-generated." + description='Optional standard visual card (300x400px) for displaying this format in user interfaces. Can be rendered via preview_creative or pre-generated.' ), ] = None format_card_detailed: Annotated[ FormatCardDetailed | None, Field( - description="Optional detailed card with carousel and full specifications. Provides rich format documentation similar to ad spec pages." + description='Optional detailed card with carousel and full specifications. Provides rich format documentation similar to ad spec pages.' ), ] = None format_id: Annotated[ format_id_1.FormatId, - Field(description="Structured format identifier with agent URL and format name"), + Field(description='Structured format identifier with agent URL and format name'), ] - name: Annotated[str, Field(description="Human-readable format name")] + name: Annotated[str, Field(description='Human-readable format name')] output_format_ids: Annotated[ list[format_id_1.FormatId] | None, Field( - description="For generative formats: array of format IDs that this format can generate. When a format accepts inputs like brand_manifest and message, this specifies what concrete output formats can be produced (e.g., a generative banner format might output standard image banner formats)." + description='For generative formats: array of format IDs that this format can generate. When a format accepts inputs like brand_manifest and message, this specifies what concrete output formats can be produced (e.g., a generative banner format might output standard image banner formats).' ), ] = None preview_image: Annotated[ AnyUrl | None, Field( - description="DEPRECATED: Use format_card instead. Optional preview image URL for format browsing/discovery UI. Should be 400x300px (4:3 aspect ratio) PNG or JPG. Used as thumbnail/card image in format browsers. This field is maintained for backward compatibility but format_card provides a more flexible, structured approach." + description='DEPRECATED: Use format_card instead. Optional preview image URL for format browsing/discovery UI. Should be 400x300px (4:3 aspect ratio) PNG or JPG. Used as thumbnail/card image in format browsers. This field is maintained for backward compatibility but format_card provides a more flexible, structured approach.' ), ] = None renders: Annotated[ list[Renders | Renders1] | None, Field( - description="Specification of rendered pieces for this format. Most formats produce a single render. Companion ad formats (video + banner), adaptive formats, and multi-placement formats produce multiple renders. Each render specifies its role and dimensions.", + description='Specification of rendered pieces for this format. Most formats produce a single render. Companion ad formats (video + banner), adaptive formats, and multi-placement formats produce multiple renders. Each render specifies its role and dimensions.', min_length=1, ), ] = None supported_macros: Annotated[ list[str] | None, Field( - description="List of universal macros supported by this format (e.g., MEDIA_BUY_ID, CACHEBUSTER, DEVICE_ID). Used for validation and developer tooling." + description='List of universal macros supported by this format (e.g., MEDIA_BUY_ID, CACHEBUSTER, DEVICE_ID). Used for validation and developer tooling.' ), ] = None type: Annotated[ format_category.FormatCategory, Field( - description="Media type of this format - determines rendering method and asset requirements" + description='Media type of this format - determines rendering method and asset requirements' ), ] diff --git a/src/adcp/types/generated_poc/core/format_id.py b/src/adcp/types/generated_poc/core/format_id.py index 99d93f83..93066e31 100644 --- a/src/adcp/types/generated_poc/core/format_id.py +++ b/src/adcp/types/generated_poc/core/format_id.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/format_id.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class FormatId(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) agent_url: Annotated[ AnyUrl, @@ -23,14 +23,14 @@ class FormatId(AdCPBaseModel): duration_ms: Annotated[ float | None, Field( - description="Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters.", + description='Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters.', ge=1.0, ), ] = None height: Annotated[ int | None, Field( - description="Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants.", + description='Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants.', ge=1, ), ] = None @@ -38,13 +38,13 @@ class FormatId(AdCPBaseModel): str, Field( description="Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant.", - pattern="^[a-zA-Z0-9_-]+$", + pattern='^[a-zA-Z0-9_-]+$', ), ] width: Annotated[ int | None, Field( - description="Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants.", + description='Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants.', ge=1, ), ] = None diff --git a/src/adcp/types/generated_poc/core/frequency_cap.py b/src/adcp/types/generated_poc/core/frequency_cap.py index 1b033db6..06c6ce02 100644 --- a/src/adcp/types/generated_poc/core/frequency_cap.py +++ b/src/adcp/types/generated_poc/core/frequency_cap.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/frequency_cap.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,8 +12,8 @@ class FrequencyCap(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) suppress_minutes: Annotated[ - float, Field(description="Minutes to suppress after impression", ge=0.0) + float, Field(description='Minutes to suppress after impression', ge=0.0) ] diff --git a/src/adcp/types/generated_poc/core/identifier.py b/src/adcp/types/generated_poc/core/identifier.py index 9b950706..8d03486f 100644 --- a/src/adcp/types/generated_poc/core/identifier.py +++ b/src/adcp/types/generated_poc/core/identifier.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/identifier.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,10 +14,10 @@ class Identifier(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) type: Annotated[ - identifier_types.PropertyIdentifierTypes, Field(description="Type of identifier") + identifier_types.PropertyIdentifierTypes, Field(description='Type of identifier') ] value: Annotated[ str, diff --git a/src/adcp/types/generated_poc/core/mcp_webhook_payload.py b/src/adcp/types/generated_poc/core/mcp_webhook_payload.py index 89670219..7049dfbf 100644 --- a/src/adcp/types/generated_poc/core/mcp_webhook_payload.py +++ b/src/adcp/types/generated_poc/core/mcp_webhook_payload.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/mcp_webhook_payload.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,56 +16,56 @@ class McpWebhookPayload(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context_id: Annotated[ str | None, Field( - description="Session/conversation identifier. Use this to continue the conversation if input-required status needs clarification or additional parameters." + description='Session/conversation identifier. Use this to continue the conversation if input-required status needs clarification or additional parameters.' ), ] = None domain: Annotated[ adcp_domain.AdcpDomain | None, Field( - description="AdCP domain this task belongs to. Helps classify the operation type at a high level." + description='AdCP domain this task belongs to. Helps classify the operation type at a high level.' ), ] = None message: Annotated[ str | None, Field( - description="Human-readable summary of the current task state. Provides context about what happened and what action may be needed." + description='Human-readable summary of the current task state. Provides context about what happened and what action may be needed.' ), ] = None operation_id: Annotated[ str | None, Field( - description="Publisher-defined operation identifier correlating a sequence of task updates across webhooks." + description='Publisher-defined operation identifier correlating a sequence of task updates across webhooks.' ), ] = None result: Annotated[ async_response_data.AdcpAsyncResponseData | None, Field( - description="Task-specific payload matching the status. For completed/failed, contains the full task response. For working/input-required/submitted, contains status-specific data. This is the data layer that AdCP specs - same structure used in A2A status.message.parts[].data." + description='Task-specific payload matching the status. For completed/failed, contains the full task response. For working/input-required/submitted, contains status-specific data. This is the data layer that AdCP specs - same structure used in A2A status.message.parts[].data.' ), ] = None status: Annotated[ task_status.TaskStatus, Field( - description="Current task status. Webhooks are triggered for status changes after initial submission." + description='Current task status. Webhooks are triggered for status changes after initial submission.' ), ] task_id: Annotated[ str, Field( - description="Unique identifier for this task. Use this to correlate webhook notifications with the original task submission." + description='Unique identifier for this task. Use this to correlate webhook notifications with the original task submission.' ), ] task_type: Annotated[ task_type_1.TaskType, Field( - description="Type of AdCP operation that triggered this webhook. Enables webhook handlers to route to appropriate processing logic." + description='Type of AdCP operation that triggered this webhook. Enables webhook handlers to route to appropriate processing logic.' ), ] timestamp: Annotated[ - AwareDatetime, Field(description="ISO 8601 timestamp when this webhook was generated.") + AwareDatetime, Field(description='ISO 8601 timestamp when this webhook was generated.') ] diff --git a/src/adcp/types/generated_poc/core/measurement.py b/src/adcp/types/generated_poc/core/measurement.py index 4188b781..f255f85d 100644 --- a/src/adcp/types/generated_poc/core/measurement.py +++ b/src/adcp/types/generated_poc/core/measurement.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/measurement.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,29 +12,29 @@ class Measurement(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) attribution: Annotated[ str, Field( - description="Attribution methodology", - examples=["deterministic_purchase", "probabilistic"], + description='Attribution methodology', + examples=['deterministic_purchase', 'probabilistic'], ), ] reporting: Annotated[ str, Field( - description="Reporting frequency and format", - examples=["weekly_dashboard", "real_time_api"], + description='Reporting frequency and format', + examples=['weekly_dashboard', 'real_time_api'], ), ] type: Annotated[ str, Field( - description="Type of measurement", - examples=["incremental_sales_lift", "brand_lift", "foot_traffic"], + description='Type of measurement', + examples=['incremental_sales_lift', 'brand_lift', 'foot_traffic'], ), ] window: Annotated[ - str | None, Field(description="Attribution window", examples=["30_days", "7_days"]) + str | None, Field(description='Attribution window', examples=['30_days', '7_days']) ] = None diff --git a/src/adcp/types/generated_poc/core/media_buy.py b/src/adcp/types/generated_poc/core/media_buy.py index 8fa3f281..41e78d09 100644 --- a/src/adcp/types/generated_poc/core/media_buy.py +++ b/src/adcp/types/generated_poc/core/media_buy.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/media_buy.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,25 +16,25 @@ class MediaBuy(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) buyer_ref: Annotated[ str | None, Field(description="Buyer's reference identifier for this media buy") ] = None - created_at: Annotated[AwareDatetime | None, Field(description="Creation timestamp")] = None + created_at: Annotated[AwareDatetime | None, Field(description='Creation timestamp')] = None creative_deadline: Annotated[ - AwareDatetime | None, Field(description="ISO 8601 timestamp for creative upload deadline") + AwareDatetime | None, Field(description='ISO 8601 timestamp for creative upload deadline') ] = None ext: ext_1.ExtensionObject | None = None media_buy_id: Annotated[ str, Field(description="Publisher's unique identifier for the media buy") ] packages: Annotated[ - list[package.Package], Field(description="Array of packages within this media buy") + list[package.Package], Field(description='Array of packages within this media buy') ] promoted_offering: Annotated[ - str, Field(description="Description of advertiser and what is being promoted") + str, Field(description='Description of advertiser and what is being promoted') ] status: media_buy_status.MediaBuyStatus - total_budget: Annotated[float, Field(description="Total budget amount", ge=0.0)] - updated_at: Annotated[AwareDatetime | None, Field(description="Last update timestamp")] = None + total_budget: Annotated[float, Field(description='Total budget amount', ge=0.0)] + updated_at: Annotated[AwareDatetime | None, Field(description='Last update timestamp')] = None diff --git a/src/adcp/types/generated_poc/core/media_buy_features.py b/src/adcp/types/generated_poc/core/media_buy_features.py new file mode 100644 index 00000000..4ec0071d --- /dev/null +++ b/src/adcp/types/generated_poc/core/media_buy_features.py @@ -0,0 +1,29 @@ +# generated by datamodel-codegen: +# filename: core/media_buy_features.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import Field + + +class MediaBuyFeatures(AdCPBaseModel): + content_standards: Annotated[ + bool | None, + Field( + description='Full support for content_standards configuration including sampling rates and category filtering' + ), + ] = None + inline_creative_management: Annotated[ + bool | None, + Field(description='Supports creatives provided inline in create_media_buy requests'), + ] = None + property_list_filtering: Annotated[ + bool | None, + Field( + description='Honors property_list parameter in get_products to filter results to buyer-approved properties' + ), + ] = None diff --git a/src/adcp/types/generated_poc/core/offering.py b/src/adcp/types/generated_poc/core/offering.py new file mode 100644 index 00000000..76050dd7 --- /dev/null +++ b/src/adcp/types/generated_poc/core/offering.py @@ -0,0 +1,80 @@ +# generated by datamodel-codegen: +# filename: core/offering.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated, Any + +from adcp.types.base import AdCPBaseModel +from pydantic import AnyUrl, AwareDatetime, ConfigDict, Field + +from . import ext as ext_1 + + +class Offering(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + assets: Annotated[ + list[dict[str, Any]] | None, + Field(description='Assets specific to this offering (images, videos, copy)'), + ] = None + categories: Annotated[ + list[str] | None, + Field( + description="Categories this offering belongs to (e.g., 'measurement', 'identity', 'programmatic')" + ), + ] = None + checkout_url: Annotated[ + AnyUrl | None, + Field( + description="URL for checkout/purchase flow when the brand doesn't support agentic checkout." + ), + ] = None + description: Annotated[str | None, Field(description="Description of what's being offered")] = ( + None + ) + ext: ext_1.ExtensionObject | None = None + keywords: Annotated[ + list[str] | None, + Field( + description='Keywords for matching this offering to user intent. Hosts use these for retrieval/relevance scoring.' + ), + ] = None + landing_url: Annotated[ + AnyUrl | None, Field(description='Landing page URL for this offering.') + ] = None + name: Annotated[ + str, + Field( + description="Human-readable offering name (e.g., 'Winter Sale', 'Free Trial', 'Enterprise Platform')" + ), + ] + offering_id: Annotated[ + str, + Field( + description='Unique identifier for this offering. Used by hosts to reference specific offerings in si_get_offering calls.' + ), + ] + portfolio_ref: Annotated[ + AnyUrl | None, + Field( + description='Reference to a creative portfolio for this offering. Portfolios contain organized creative assets across formats, enabling consistent ad delivery for this specific offering.' + ), + ] = None + tagline: Annotated[ + str | None, Field(description='Short promotional tagline for the offering') + ] = None + valid_from: Annotated[ + AwareDatetime | None, + Field( + description='When the offering becomes available. If not specified, offering is immediately available.' + ), + ] = None + valid_to: Annotated[ + AwareDatetime | None, + Field( + description='When the offering expires. If not specified, offering has no expiration.' + ), + ] = None diff --git a/src/adcp/types/generated_poc/core/package.py b/src/adcp/types/generated_poc/core/package.py index 397d1ee2..f2199bd5 100644 --- a/src/adcp/types/generated_poc/core/package.py +++ b/src/adcp/types/generated_poc/core/package.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/package.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,19 +17,19 @@ class Package(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) bid_price: Annotated[ float | None, Field( - description="Bid price for auction-based CPM pricing (present if using cpm-auction-option)", + description='Bid price for auction-based CPM pricing (present if using cpm-auction-option)', ge=0.0, ), ] = None budget: Annotated[ float | None, Field( - description="Budget allocation for this package in the currency specified by the pricing option", + description='Budget allocation for this package in the currency specified by the pricing option', ge=0.0, ), ] = None @@ -38,22 +38,22 @@ class Package(AdCPBaseModel): ] = None creative_assignments: Annotated[ list[creative_assignment.CreativeAssignment] | None, - Field(description="Creative assets assigned to this package"), + Field(description='Creative assets assigned to this package'), ] = None ext: ext_1.ExtensionObject | None = None format_ids_to_provide: Annotated[ list[format_id.FormatId] | None, - Field(description="Format IDs that creative assets will be provided for this package"), + Field(description='Format IDs that creative assets will be provided for this package'), ] = None impressions: Annotated[ - float | None, Field(description="Impression goal for this package", ge=0.0) + float | None, Field(description='Impression goal for this package', ge=0.0) ] = None pacing: pacing_1.Pacing | None = None package_id: Annotated[str, Field(description="Publisher's unique identifier for the package")] paused: Annotated[ bool | None, Field( - description="Whether this package is paused by the buyer. Paused packages do not deliver impressions. Defaults to false." + description='Whether this package is paused by the buyer. Paused packages do not deliver impressions. Defaults to false.' ), ] = False pricing_option_id: Annotated[ @@ -63,6 +63,6 @@ class Package(AdCPBaseModel): ), ] = None product_id: Annotated[ - str | None, Field(description="ID of the product this package is based on") + str | None, Field(description='ID of the product this package is based on') ] = None targeting_overlay: targeting.TargetingOverlay | None = None diff --git a/src/adcp/types/generated_poc/core/performance_feedback.py b/src/adcp/types/generated_poc/core/performance_feedback.py index d2630b80..a11e157a 100644 --- a/src/adcp/types/generated_poc/core/performance_feedback.py +++ b/src/adcp/types/generated_poc/core/performance_feedback.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/performance_feedback.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,63 +16,63 @@ class MeasurementPeriod(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) end: Annotated[ - AwareDatetime, Field(description="ISO 8601 end timestamp for measurement period") + AwareDatetime, Field(description='ISO 8601 end timestamp for measurement period') ] start: Annotated[ - AwareDatetime, Field(description="ISO 8601 start timestamp for measurement period") + AwareDatetime, Field(description='ISO 8601 start timestamp for measurement period') ] class Status(Enum): - accepted = "accepted" - queued = "queued" - applied = "applied" - rejected = "rejected" + accepted = 'accepted' + queued = 'queued' + applied = 'applied' + rejected = 'rejected' class PerformanceFeedback(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) applied_at: Annotated[ AwareDatetime | None, Field( - description="ISO 8601 timestamp when feedback was applied to optimization algorithms" + description='ISO 8601 timestamp when feedback was applied to optimization algorithms' ), ] = None creative_id: Annotated[ - str | None, Field(description="Specific creative asset (if feedback is creative-specific)") + str | None, Field(description='Specific creative asset (if feedback is creative-specific)') ] = None feedback_id: Annotated[ - str, Field(description="Unique identifier for this performance feedback submission") + str, Field(description='Unique identifier for this performance feedback submission') ] feedback_source: Annotated[ - feedback_source_1.FeedbackSource, Field(description="Source of the performance data") + feedback_source_1.FeedbackSource, Field(description='Source of the performance data') ] measurement_period: Annotated[ - MeasurementPeriod, Field(description="Time period for performance measurement") + MeasurementPeriod, Field(description='Time period for performance measurement') ] media_buy_id: Annotated[str, Field(description="Publisher's media buy identifier")] metric_type: Annotated[ - metric_type_1.MetricType, Field(description="The business metric being measured") + metric_type_1.MetricType, Field(description='The business metric being measured') ] package_id: Annotated[ str | None, Field( - description="Specific package within the media buy (if feedback is package-specific)" + description='Specific package within the media buy (if feedback is package-specific)' ), ] = None performance_index: Annotated[ float, Field( - description="Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected)", + description='Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected)', ge=0.0, ), ] - status: Annotated[Status, Field(description="Processing status of the performance feedback")] + status: Annotated[Status, Field(description='Processing status of the performance feedback')] submitted_at: Annotated[ - AwareDatetime, Field(description="ISO 8601 timestamp when feedback was submitted") + AwareDatetime, Field(description='ISO 8601 timestamp when feedback was submitted') ] diff --git a/src/adcp/types/generated_poc/core/placement.py b/src/adcp/types/generated_poc/core/placement.py index 5d905f45..8d2eec52 100644 --- a/src/adcp/types/generated_poc/core/placement.py +++ b/src/adcp/types/generated_poc/core/placement.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/placement.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,15 +14,15 @@ class Placement(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) description: Annotated[ - str | None, Field(description="Detailed description of where and how the placement appears") + str | None, Field(description='Detailed description of where and how the placement appears') ] = None format_ids: Annotated[ list[format_id.FormatId] | None, Field( - description="Format IDs supported by this specific placement. Can include: (1) concrete format_ids (fixed dimensions), (2) template format_ids without parameters (accepts any dimensions/duration), or (3) parameterized format_ids (specific dimension/duration constraints).", + description='Format IDs supported by this specific placement. Can include: (1) concrete format_ids (fixed dimensions), (2) template format_ids without parameters (accepts any dimensions/duration), or (3) parameterized format_ids (specific dimension/duration constraints).', min_length=1, ), ] = None @@ -33,5 +33,5 @@ class Placement(AdCPBaseModel): ), ] placement_id: Annotated[ - str, Field(description="Unique identifier for the placement within the product") + str, Field(description='Unique identifier for the placement within the product') ] diff --git a/src/adcp/types/generated_poc/core/pricing_option.py b/src/adcp/types/generated_poc/core/pricing_option.py index 37fb85b2..400af6c0 100644 --- a/src/adcp/types/generated_poc/core/pricing_option.py +++ b/src/adcp/types/generated_poc/core/pricing_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/pricing_option.json -# timestamp: 2025-12-11T15:09:37+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -45,7 +45,7 @@ class PricingOption( | cpp_option.CppPricingOption | flat_rate_option.FlatRatePricingOption, Field( - description="A pricing model option offered by a publisher for a product. Each pricing model has its own schema with model-specific requirements.", - title="Pricing Option", + description='A pricing model option offered by a publisher for a product. Each pricing model has its own schema with model-specific requirements.', + title='Pricing Option', ), ] diff --git a/src/adcp/types/generated_poc/core/product.py b/src/adcp/types/generated_poc/core/product.py index adc5576b..4dfe9274 100644 --- a/src/adcp/types/generated_poc/core/product.py +++ b/src/adcp/types/generated_poc/core/product.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/product.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -35,100 +35,100 @@ class DeliveryMeasurement(AdCPBaseModel): class ProductCard(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) format_id: Annotated[ format_id_1.FormatId, Field( - description="Creative format defining the card layout (typically product_card_standard)" + description='Creative format defining the card layout (typically product_card_standard)' ), ] manifest: Annotated[ dict[str, Any], - Field(description="Asset manifest for rendering the card, structure defined by the format"), + Field(description='Asset manifest for rendering the card, structure defined by the format'), ] class ProductCardDetailed(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) format_id: Annotated[ format_id_1.FormatId, Field( - description="Creative format defining the detailed card layout (typically product_card_detailed)" + description='Creative format defining the detailed card layout (typically product_card_detailed)' ), ] manifest: Annotated[ dict[str, Any], Field( - description="Asset manifest for rendering the detailed card, structure defined by the format" + description='Asset manifest for rendering the detailed card, structure defined by the format' ), ] class Product(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) brief_relevance: Annotated[ str | None, Field( - description="Explanation of why this product matches the brief (only included when brief is provided)" + description='Explanation of why this product matches the brief (only included when brief is provided)' ), ] = None creative_policy: creative_policy_1.CreativePolicy | None = None delivery_measurement: Annotated[ DeliveryMeasurement, Field( - description="Measurement provider and methodology for delivery metrics. The buyer accepts the declared provider as the source of truth for the buy. REQUIRED for all products." + description='Measurement provider and methodology for delivery metrics. The buyer accepts the declared provider as the source of truth for the buy. REQUIRED for all products.' ), ] delivery_type: delivery_type_1.DeliveryType description: Annotated[ - str, Field(description="Detailed description of the product and its inventory") + str, Field(description='Detailed description of the product and its inventory') ] estimated_exposures: Annotated[ int | None, - Field(description="Estimated exposures/impressions for guaranteed products", ge=0), + Field(description='Estimated exposures/impressions for guaranteed products', ge=0), ] = None expires_at: Annotated[ - AwareDatetime | None, Field(description="Expiration timestamp for custom products") + AwareDatetime | None, Field(description='Expiration timestamp for custom products') ] = None ext: ext_1.ExtensionObject | None = None format_ids: Annotated[ list[format_id_1.FormatId], Field( - description="Array of supported creative format IDs - structured format_id objects with agent_url and id" + description='Array of supported creative format IDs - structured format_id objects with agent_url and id' ), ] - is_custom: Annotated[bool | None, Field(description="Whether this is a custom product")] = None + is_custom: Annotated[bool | None, Field(description='Whether this is a custom product')] = None measurement: measurement_1.Measurement | None = None - name: Annotated[str, Field(description="Human-readable product name")] + name: Annotated[str, Field(description='Human-readable product name')] placements: Annotated[ list[placement.Placement] | None, Field( - description="Optional array of specific placements within this product. When provided, buyers can target specific placements when assigning creatives.", + description='Optional array of specific placements within this product. When provided, buyers can target specific placements when assigning creatives.', min_length=1, ), ] = None pricing_options: Annotated[ list[pricing_option.PricingOption], - Field(description="Available pricing models for this product", min_length=1), + Field(description='Available pricing models for this product', min_length=1), ] product_card: Annotated[ ProductCard | None, Field( - description="Optional standard visual card (300x400px) for displaying this product in user interfaces. Can be rendered via preview_creative or pre-generated." + description='Optional standard visual card (300x400px) for displaying this product in user interfaces. Can be rendered via preview_creative or pre-generated.' ), ] = None product_card_detailed: Annotated[ ProductCardDetailed | None, Field( - description="Optional detailed card with carousel and full specifications. Provides rich product presentation similar to media kit pages." + description='Optional detailed card with carousel and full specifications. Provides rich product presentation similar to media kit pages.' ), ] = None - product_id: Annotated[str, Field(description="Unique identifier for the product")] + product_id: Annotated[str, Field(description='Unique identifier for the product')] publisher_properties: Annotated[ list[publisher_property_selector.PublisherPropertySelector], Field( diff --git a/src/adcp/types/generated_poc/core/product_allocation.py b/src/adcp/types/generated_poc/core/product_allocation.py new file mode 100644 index 00000000..b5bdeeb3 --- /dev/null +++ b/src/adcp/types/generated_poc/core/product_allocation.py @@ -0,0 +1,48 @@ +# generated by datamodel-codegen: +# filename: core/product_allocation.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field + +from . import ext as ext_1 + + +class ProductAllocation(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + allocation_percentage: Annotated[ + float, + Field( + description='Percentage of total budget allocated to this product (0-100)', + ge=0.0, + le=100.0, + ), + ] + ext: ext_1.ExtensionObject | None = None + pricing_option_id: Annotated[ + str | None, + Field(description="Recommended pricing option ID from the product's pricing_options array"), + ] = None + product_id: Annotated[ + str, Field(description='ID of the product (must reference a product in the products array)') + ] + rationale: Annotated[ + str | None, + Field(description='Explanation of why this product and allocation are recommended'), + ] = None + sequence: Annotated[ + int | None, + Field(description='Optional ordering hint for multi-line-item plans (1-based)', ge=1), + ] = None + tags: Annotated[ + list[str] | None, + Field( + description="Categorical tags for this allocation (e.g., 'desktop', 'german', 'mobile') - useful for grouping/filtering allocations by dimension" + ), + ] = None diff --git a/src/adcp/types/generated_poc/core/product_filters.py b/src/adcp/types/generated_poc/core/product_filters.py index 27168ed5..441931b3 100644 --- a/src/adcp/types/generated_poc/core/product_filters.py +++ b/src/adcp/types/generated_poc/core/product_filters.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/product_filters.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,90 +8,152 @@ from typing import Annotated from adcp.types.base import AdCPBaseModel -from pydantic import ConfigDict, Field, RootModel +from pydantic import AnyUrl, ConfigDict, Field, RootModel from ..enums import channels as channels_1 from ..enums import delivery_type as delivery_type_1 -from ..enums import format_category -from . import format_id +from ..enums import format_category, geo_level, metro_system +from . import format_id, media_buy_features class BudgetRange(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) currency: Annotated[ str, Field( - description="ISO 4217 currency code (e.g., 'USD', 'EUR', 'GBP')", pattern="^[A-Z]{3}$" + description="ISO 4217 currency code (e.g., 'USD', 'EUR', 'GBP')", pattern='^[A-Z]{3}$' ), ] - max: Annotated[float | None, Field(description="Maximum budget amount", ge=0.0)] = None - min: Annotated[float, Field(description="Minimum budget amount", ge=0.0)] + max: Annotated[float | None, Field(description='Maximum budget amount', ge=0.0)] = None + min: Annotated[float, Field(description='Minimum budget amount', ge=0.0)] class BudgetRange1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) currency: Annotated[ str, Field( - description="ISO 4217 currency code (e.g., 'USD', 'EUR', 'GBP')", pattern="^[A-Z]{3}$" + description="ISO 4217 currency code (e.g., 'USD', 'EUR', 'GBP')", pattern='^[A-Z]{3}$' ), ] - max: Annotated[float, Field(description="Maximum budget amount", ge=0.0)] - min: Annotated[float | None, Field(description="Minimum budget amount", ge=0.0)] = None + max: Annotated[float, Field(description='Maximum budget amount', ge=0.0)] + min: Annotated[float | None, Field(description='Minimum budget amount', ge=0.0)] = None class Country(RootModel[str]): - root: Annotated[str, Field(pattern="^[A-Z]{2}$")] + root: Annotated[str, Field(pattern='^[A-Z]{2}$')] + + +class Metro(AdCPBaseModel): + model_config = ConfigDict( + extra='forbid', + ) + code: Annotated[ + str, Field(description="Metro code within the system (e.g., '501' for NYC DMA)") + ] + system: Annotated[ + metro_system.MetroAreaSystem, Field(description='Metro classification system') + ] + + +class Region(RootModel[str]): + root: Annotated[str, Field(pattern='^[A-Z]{2}-[A-Z0-9]+$')] + + +class RequiredGeoTargetingItem(AdCPBaseModel): + model_config = ConfigDict( + extra='forbid', + ) + level: Annotated[ + geo_level.GeographicTargetingLevel, + Field(description='Geographic targeting level (country, region, metro, postal_area)'), + ] + system: Annotated[ + str | None, + Field( + description="Classification system within the level. Required for metro (e.g., 'nielsen_dma') and postal_area (e.g., 'us_zip'). Not applicable for country/region which use ISO standards." + ), + ] = None class ProductFilters(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) budget_range: Annotated[ BudgetRange | BudgetRange1 | None, - Field(description="Budget range to filter appropriate products"), + Field(description='Budget range to filter appropriate products'), ] = None channels: Annotated[ - list[channels_1.AdvertisingChannels] | None, + list[channels_1.MediaChannel] | None, Field(description="Filter by advertising channels (e.g., ['display', 'video', 'dooh'])"), ] = None countries: Annotated[ list[Country] | None, Field( - description="Filter by target countries using ISO 3166-1 alpha-2 country codes (e.g., ['US', 'CA', 'GB'])" + description="Filter by country coverage using ISO 3166-1 alpha-2 codes (e.g., ['US', 'CA', 'GB']). Works for all inventory types." ), ] = None delivery_type: delivery_type_1.DeliveryType | None = None end_date: Annotated[ date | None, Field( - description="Campaign end date (ISO 8601 date format: YYYY-MM-DD) for availability checks" + description='Campaign end date (ISO 8601 date format: YYYY-MM-DD) for availability checks' ), ] = None format_ids: Annotated[ - list[format_id.FormatId] | None, Field(description="Filter by specific format IDs") + list[format_id.FormatId] | None, Field(description='Filter by specific format IDs') ] = None format_types: Annotated[ - list[format_category.FormatCategory] | None, Field(description="Filter by format types") + list[format_category.FormatCategory] | None, Field(description='Filter by format types') ] = None is_fixed_price: Annotated[ - bool | None, Field(description="Filter for fixed price vs auction products") + bool | None, Field(description='Filter for fixed price vs auction products') + ] = None + metros: Annotated[ + list[Metro] | None, + Field( + description='Filter by metro coverage for locally-bound inventory (radio, DOOH, local TV). Use when products have DMA/metro-specific coverage. For digital inventory where products have broad coverage, use required_geo_targeting instead to filter by seller capability.' + ), ] = None min_exposures: Annotated[ int | None, - Field(description="Minimum exposures/impressions needed for measurement validity", ge=1), + Field(description='Minimum exposures/impressions needed for measurement validity', ge=1), + ] = None + regions: Annotated[ + list[Region] | None, + Field( + description="Filter by region coverage using ISO 3166-2 codes (e.g., ['US-NY', 'US-CA', 'GB-SCT']). Use for locally-bound inventory (regional OOH, local TV) where products have region-specific coverage." + ), + ] = None + required_axe_integrations: Annotated[ + list[AnyUrl] | None, + Field( + description='Filter to products executable through specific agentic ad exchanges. URLs are canonical identifiers.' + ), + ] = None + required_features: Annotated[ + media_buy_features.MediaBuyFeatures | None, + Field( + description='Filter to products from sellers supporting specific protocol features. Only features set to true are used for filtering.' + ), + ] = None + required_geo_targeting: Annotated[ + list[RequiredGeoTargetingItem] | None, + Field( + description='Filter to products from sellers supporting specific geo targeting capabilities. Each entry specifies a targeting level (country, region, metro, postal_area) and optionally a system for levels that have multiple classification systems.' + ), ] = None standard_formats_only: Annotated[ - bool | None, Field(description="Only return products accepting IAB standard formats") + bool | None, Field(description='Only return products accepting IAB standard formats') ] = None start_date: Annotated[ date | None, Field( - description="Campaign start date (ISO 8601 date format: YYYY-MM-DD) for availability checks" + description='Campaign start date (ISO 8601 date format: YYYY-MM-DD) for availability checks' ), ] = None diff --git a/src/adcp/types/generated_poc/core/promoted_offerings.py b/src/adcp/types/generated_poc/core/promoted_offerings.py index acf4f68d..bdb0fe72 100644 --- a/src/adcp/types/generated_poc/core/promoted_offerings.py +++ b/src/adcp/types/generated_poc/core/promoted_offerings.py @@ -1,41 +1,41 @@ # generated by datamodel-codegen: # filename: core/promoted_offerings.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations from enum import Enum -from typing import Annotated, Any +from typing import Annotated from adcp.types.base import AdCPBaseModel -from pydantic import ConfigDict, Field +from pydantic import AnyUrl, ConfigDict, Field -from . import brand_manifest_ref, promoted_products +from . import brand_manifest_ref, offering, promoted_products class AssetType(Enum): - image = "image" - video = "video" - audio = "audio" - vast = "vast" - daast = "daast" - text = "text" - url = "url" - html = "html" - css = "css" - javascript = "javascript" - webhook = "webhook" + image = 'image' + video = 'video' + audio = 'audio' + vast = 'vast' + daast = 'daast' + text = 'text' + url = 'url' + html = 'html' + css = 'css' + javascript = 'javascript' + webhook = 'webhook' class AssetSelectors(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) asset_types: Annotated[ list[AssetType] | None, Field(description="Filter by asset type (e.g., ['image', 'video'])") ] = None exclude_tags: Annotated[ - list[str] | None, Field(description="Exclude assets with these tags") + list[str] | None, Field(description='Exclude assets with these tags') ] = None tags: Annotated[ list[str] | None, @@ -43,44 +43,35 @@ class AssetSelectors(AdCPBaseModel): ] = None -class Offering(AdCPBaseModel): - model_config = ConfigDict( - extra="allow", - ) - assets: Annotated[ - list[dict[str, Any]] | None, Field(description="Assets specific to this offering") - ] = None - description: Annotated[str | None, Field(description="Description of what's being offered")] = ( - None - ) - name: Annotated[ - str, Field(description="Offering name (e.g., 'Winter Sale', 'New Product Launch')") - ] - - class PromotedOfferings(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) asset_selectors: Annotated[ AssetSelectors | None, - Field(description="Selectors to choose specific assets from the brand manifest"), + Field(description='Selectors to choose specific assets from the brand manifest'), ] = None brand_manifest: Annotated[ brand_manifest_ref.BrandManifestReference, Field( - description="Brand information manifest containing assets, themes, and guidelines. Can be provided inline or as a URL reference to a hosted manifest." + description='Brand information manifest containing assets, themes, and guidelines. Can be provided inline or as a URL reference to a hosted manifest.' ), ] offerings: Annotated[ - list[Offering] | None, + list[offering.Offering] | None, Field( - description="Inline offerings for campaigns without a product catalog. Each offering has a name, description, and associated assets." + description='Offerings available for promotion. Each offering can include creative assets (via portfolio_ref or inline assets) for traditional ads. When si_agent_url is set at the parent level, hosts can offer conversational experiences about any of these offerings.' ), ] = None product_selectors: Annotated[ promoted_products.PromotedProducts | None, Field( - description="Selectors to choose which products/offerings from the brand manifest product catalog to promote" + description='Selectors to choose which products/offerings from the brand manifest product catalog to promote' + ), + ] = None + si_agent_url: Annotated[ + AnyUrl | None, + Field( + description="MCP endpoint URL for the brand's SI agent. When present, hosts can connect users to conversational experiences about any of the offerings. The agent handles si_get_offering lookups and full conversations." ), ] = None diff --git a/src/adcp/types/generated_poc/core/promoted_products.py b/src/adcp/types/generated_poc/core/promoted_products.py index c24e5e76..8c917fd7 100644 --- a/src/adcp/types/generated_poc/core/promoted_products.py +++ b/src/adcp/types/generated_poc/core/promoted_products.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/promoted_products.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class PromotedProducts(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) manifest_category: Annotated[ str | None, @@ -28,7 +28,7 @@ class PromotedProducts(AdCPBaseModel): ] = None manifest_skus: Annotated[ list[str] | None, - Field(description="Direct product SKU references from the brand manifest product catalog"), + Field(description='Direct product SKU references from the brand manifest product catalog'), ] = None manifest_tags: Annotated[ list[str] | None, diff --git a/src/adcp/types/generated_poc/core/property.py b/src/adcp/types/generated_poc/core/property.py index 5eea8a14..1f17eaae 100644 --- a/src/adcp/types/generated_poc/core/property.py +++ b/src/adcp/types/generated_poc/core/property.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/property.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,11 +17,11 @@ class Identifier(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) type: Annotated[ identifier_types.PropertyIdentifierTypes, - Field(description="Type of identifier for this property"), + Field(description='Type of identifier for this property'), ] value: Annotated[ str, @@ -33,30 +33,30 @@ class Identifier(AdCPBaseModel): class Property(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) identifiers: Annotated[ - list[Identifier], Field(description="Array of identifiers for this property", min_length=1) + list[Identifier], Field(description='Array of identifiers for this property', min_length=1) ] - name: Annotated[str, Field(description="Human-readable property name")] + name: Annotated[str, Field(description='Human-readable property name')] property_id: Annotated[ property_id_1.PropertyId | None, Field( - description="Unique identifier for this property (optional). Enables referencing properties by ID instead of repeating full objects." + description='Unique identifier for this property (optional). Enables referencing properties by ID instead of repeating full objects.' ), ] = None property_type: Annotated[ - property_type_1.PropertyType, Field(description="Type of advertising property") + property_type_1.PropertyType, Field(description='Type of advertising property') ] publisher_domain: Annotated[ str | None, Field( - description="Domain where adagents.json should be checked for authorization validation. Required for list_authorized_properties response. Optional in adagents.json (file location implies domain)." + description='Domain where adagents.json should be checked for authorization validation. Required for list_authorized_properties response. Optional in adagents.json (file location implies domain).' ), ] = None tags: Annotated[ list[property_tag.PropertyTag] | None, Field( - description="Tags for categorization and grouping (e.g., network membership, content categories)" + description='Tags for categorization and grouping (e.g., network membership, content categories)' ), ] = None diff --git a/src/adcp/types/generated_poc/core/property_id.py b/src/adcp/types/generated_poc/core/property_id.py index d282b8e6..1536816c 100644 --- a/src/adcp/types/generated_poc/core/property_id.py +++ b/src/adcp/types/generated_poc/core/property_id.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/property_id.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -13,9 +13,9 @@ class PropertyId(RootModel[str]): root: Annotated[ str, Field( - description="Identifier for a publisher property. Must be lowercase alphanumeric with underscores only.", - examples=["cnn_ctv_app", "homepage", "mobile_ios", "instagram"], - pattern="^[a-z0-9_]+$", - title="Property ID", + description='Identifier for a publisher property. Must be lowercase alphanumeric with underscores only.', + examples=['cnn_ctv_app', 'homepage', 'mobile_ios', 'instagram'], + pattern='^[a-z0-9_]+$', + title='Property ID', ), ] diff --git a/src/adcp/types/generated_poc/core/property_list_ref.py b/src/adcp/types/generated_poc/core/property_list_ref.py index 0bf08373..846c8511 100644 --- a/src/adcp/types/generated_poc/core/property_list_ref.py +++ b/src/adcp/types/generated_poc/core/property_list_ref.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/property_list_ref.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,15 +12,15 @@ class PropertyListReference(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) - agent_url: Annotated[AnyUrl, Field(description="URL of the agent managing the property list")] + agent_url: Annotated[AnyUrl, Field(description='URL of the agent managing the property list')] auth_token: Annotated[ str | None, Field( - description="JWT or other authorization token for accessing the list. Optional if the list is public or caller has implicit access." + description='JWT or other authorization token for accessing the list. Optional if the list is public or caller has implicit access.' ), ] = None list_id: Annotated[ - str, Field(description="Identifier for the property list within the agent", min_length=1) + str, Field(description='Identifier for the property list within the agent', min_length=1) ] diff --git a/src/adcp/types/generated_poc/core/property_tag.py b/src/adcp/types/generated_poc/core/property_tag.py index f681eaa1..cbd0fd86 100644 --- a/src/adcp/types/generated_poc/core/property_tag.py +++ b/src/adcp/types/generated_poc/core/property_tag.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/property_tag.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -13,9 +13,9 @@ class PropertyTag(RootModel[str]): root: Annotated[ str, Field( - description="Tag for categorizing publisher properties. Must be lowercase alphanumeric with underscores only.", - examples=["ctv", "premium", "news", "sports", "meta_network", "social_media"], - pattern="^[a-z0-9_]+$", - title="Property Tag", + description='Tag for categorizing publisher properties. Must be lowercase alphanumeric with underscores only.', + examples=['ctv', 'premium', 'news', 'sports', 'meta_network', 'social_media'], + pattern='^[a-z0-9_]+$', + title='Property Tag', ), ] diff --git a/src/adcp/types/generated_poc/core/proposal.py b/src/adcp/types/generated_poc/core/proposal.py new file mode 100644 index 00000000..303bb434 --- /dev/null +++ b/src/adcp/types/generated_poc/core/proposal.py @@ -0,0 +1,64 @@ +# generated by datamodel-codegen: +# filename: core/proposal.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import AwareDatetime, ConfigDict, Field + +from . import ext as ext_1 +from . import product_allocation + + +class TotalBudgetGuidance(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + currency: Annotated[str | None, Field(description='ISO 4217 currency code')] = None + max: Annotated[ + float | None, Field(description='Maximum budget before diminishing returns', ge=0.0) + ] = None + min: Annotated[float | None, Field(description='Minimum recommended budget', ge=0.0)] = None + recommended: Annotated[ + float | None, Field(description='Recommended budget for optimal performance', ge=0.0) + ] = None + + +class Proposal(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + allocations: Annotated[ + list[product_allocation.ProductAllocation], + Field( + description='Budget allocations across products. Allocation percentages MUST sum to 100. Publishers are responsible for ensuring the sum equals 100; buyers SHOULD validate this before execution.', + min_length=1, + ), + ] + brief_alignment: Annotated[ + str | None, + Field(description='Explanation of how this proposal aligns with the campaign brief'), + ] = None + description: Annotated[ + str | None, Field(description='Explanation of the proposal strategy and what it achieves') + ] = None + expires_at: Annotated[ + AwareDatetime | None, + Field( + description='When this proposal expires and can no longer be executed. After expiration, referenced products or pricing may no longer be available.' + ), + ] = None + ext: ext_1.ExtensionObject | None = None + name: Annotated[str, Field(description='Human-readable name for this media plan proposal')] + proposal_id: Annotated[ + str, + Field( + description='Unique identifier for this proposal. Used to refine the proposal in subsequent get_products calls or to execute it via create_media_buy.' + ), + ] + total_budget_guidance: Annotated[ + TotalBudgetGuidance | None, Field(description='Optional budget guidance for this proposal') + ] = None diff --git a/src/adcp/types/generated_poc/core/protocol_envelope.py b/src/adcp/types/generated_poc/core/protocol_envelope.py index f272f199..3d4d4e66 100644 --- a/src/adcp/types/generated_poc/core/protocol_envelope.py +++ b/src/adcp/types/generated_poc/core/protocol_envelope.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/protocol_envelope.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,47 +15,47 @@ class ProtocolEnvelope(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context_id: Annotated[ str | None, Field( - description="Session/conversation identifier for tracking related operations across multiple task invocations. Managed by the protocol layer to maintain conversational context." + description='Session/conversation identifier for tracking related operations across multiple task invocations. Managed by the protocol layer to maintain conversational context.' ), ] = None message: Annotated[ str | None, Field( - description="Human-readable summary of the task result. Provides natural language explanation of what happened, suitable for display to end users or for AI agent comprehension. Generated by the protocol layer based on the task response." + description='Human-readable summary of the task result. Provides natural language explanation of what happened, suitable for display to end users or for AI agent comprehension. Generated by the protocol layer based on the task response.' ), ] = None payload: Annotated[ dict[str, Any], Field( - description="The actual task-specific response data. This is the content defined in individual task response schemas (e.g., get-products-response.json, create-media-buy-response.json). Contains only domain-specific data without protocol-level fields." + description='The actual task-specific response data. This is the content defined in individual task response schemas (e.g., get-products-response.json, create-media-buy-response.json). Contains only domain-specific data without protocol-level fields.' ), ] push_notification_config: Annotated[ push_notification_config_1.PushNotificationConfig | None, Field( - description="Push notification configuration for async task updates (A2A and REST protocols). Echoed from the request to confirm webhook settings. Specifies URL, authentication scheme (Bearer or HMAC-SHA256), and credentials. MCP uses progress notifications instead of webhooks." + description='Push notification configuration for async task updates (A2A and REST protocols). Echoed from the request to confirm webhook settings. Specifies URL, authentication scheme (Bearer or HMAC-SHA256), and credentials. MCP uses progress notifications instead of webhooks.' ), ] = None status: Annotated[ task_status.TaskStatus, Field( - description="Current task execution state. Indicates whether the task is completed, in progress (working), submitted for async processing, failed, or requires user input. Managed by the protocol layer." + description='Current task execution state. Indicates whether the task is completed, in progress (working), submitted for async processing, failed, or requires user input. Managed by the protocol layer.' ), ] task_id: Annotated[ str | None, Field( - description="Unique identifier for tracking asynchronous operations. Present when a task requires extended processing time. Used to query task status and retrieve results when complete." + description='Unique identifier for tracking asynchronous operations. Present when a task requires extended processing time. Used to query task status and retrieve results when complete.' ), ] = None timestamp: Annotated[ AwareDatetime | None, Field( - description="ISO 8601 timestamp when the response was generated. Useful for debugging, logging, cache validation, and tracking async operation progress." + description='ISO 8601 timestamp when the response was generated. Useful for debugging, logging, cache validation, and tracking async operation progress.' ), ] = None diff --git a/src/adcp/types/generated_poc/core/publisher_property_selector.py b/src/adcp/types/generated_poc/core/publisher_property_selector.py index 7644a672..99a90a2e 100644 --- a/src/adcp/types/generated_poc/core/publisher_property_selector.py +++ b/src/adcp/types/generated_poc/core/publisher_property_selector.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/publisher_property_selector.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,26 +14,26 @@ class PublisherPropertySelector1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) publisher_domain: Annotated[ str, Field( description="Domain where publisher's adagents.json is hosted (e.g., 'cnn.com')", - pattern="^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$", + pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$', ), ] selection_type: Annotated[ - Literal["all"], + Literal['all'], Field( - description="Discriminator indicating all properties from this publisher are included" + description='Discriminator indicating all properties from this publisher are included' ), ] class PublisherPropertySelector2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) property_ids: Annotated[ list[property_id.PropertyId], @@ -43,18 +43,18 @@ class PublisherPropertySelector2(AdCPBaseModel): str, Field( description="Domain where publisher's adagents.json is hosted (e.g., 'cnn.com')", - pattern="^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$", + pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$', ), ] selection_type: Annotated[ - Literal["by_id"], - Field(description="Discriminator indicating selection by specific property IDs"), + Literal['by_id'], + Field(description='Discriminator indicating selection by specific property IDs'), ] class PublisherPropertySelector3(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) property_tags: Annotated[ list[property_tag.PropertyTag], @@ -67,11 +67,11 @@ class PublisherPropertySelector3(AdCPBaseModel): str, Field( description="Domain where publisher's adagents.json is hosted (e.g., 'cnn.com')", - pattern="^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$", + pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$', ), ] selection_type: Annotated[ - Literal["by_tag"], Field(description="Discriminator indicating selection by property tags") + Literal['by_tag'], Field(description='Discriminator indicating selection by property tags') ] @@ -82,7 +82,7 @@ class PublisherPropertySelector( PublisherPropertySelector1 | PublisherPropertySelector2 | PublisherPropertySelector3, Field( description="Selects properties from a publisher's adagents.json. Used for both product definitions and agent authorization. Supports three selection patterns: all properties, specific IDs, or by tags.", - discriminator="selection_type", - title="Publisher Property Selector", + discriminator='selection_type', + title='Publisher Property Selector', ), ] diff --git a/src/adcp/types/generated_poc/core/push_notification_config.py b/src/adcp/types/generated_poc/core/push_notification_config.py index 950afb9b..7a033749 100644 --- a/src/adcp/types/generated_poc/core/push_notification_config.py +++ b/src/adcp/types/generated_poc/core/push_notification_config.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/push_notification_config.json -# timestamp: 2025-12-18T20:00:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,12 +14,12 @@ class Authentication(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) credentials: Annotated[ str, Field( - description="Credentials for authentication. For Bearer: token sent in Authorization header. For HMAC-SHA256: shared secret used to generate signature. Minimum 32 characters. Exchanged out-of-band during onboarding.", + description='Credentials for authentication. For Bearer: token sent in Authorization header. For HMAC-SHA256: shared secret used to generate signature. Minimum 32 characters. Exchanged out-of-band during onboarding.', min_length=32, ), ] @@ -36,13 +36,13 @@ class Authentication(AdCPBaseModel): class PushNotificationConfig(AdCPBaseModel): authentication: Annotated[ Authentication, - Field(description="Authentication configuration for webhook delivery (A2A-compatible)"), + Field(description='Authentication configuration for webhook delivery (A2A-compatible)'), ] token: Annotated[ str | None, Field( - description="Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.", + description='Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.', min_length=16, ), ] = None - url: Annotated[AnyUrl, Field(description="Webhook endpoint URL for task status notifications")] + url: Annotated[AnyUrl, Field(description='Webhook endpoint URL for task status notifications')] diff --git a/src/adcp/types/generated_poc/core/reporting_capabilities.py b/src/adcp/types/generated_poc/core/reporting_capabilities.py index 3fae8dd7..3cabc384 100644 --- a/src/adcp/types/generated_poc/core/reporting_capabilities.py +++ b/src/adcp/types/generated_poc/core/reporting_capabilities.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/reporting_capabilities.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,38 +14,38 @@ class ReportingCapabilities(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) available_metrics: Annotated[ list[available_metric.AvailableMetric], Field( - description="Metrics available in reporting. Impressions and spend are always implicitly included.", + description='Metrics available in reporting. Impressions and spend are always implicitly included.', examples=[ - ["impressions", "spend", "clicks", "video_completions"], - ["impressions", "spend", "conversions"], + ['impressions', 'spend', 'clicks', 'video_completions'], + ['impressions', 'spend', 'conversions'], ], ), ] available_reporting_frequencies: Annotated[ list[reporting_frequency.ReportingFrequency], - Field(description="Supported reporting frequency options", min_length=1), + Field(description='Supported reporting frequency options', min_length=1), ] expected_delay_minutes: Annotated[ int, Field( - description="Expected delay in minutes before reporting data becomes available (e.g., 240 for 4-hour delay)", + description='Expected delay in minutes before reporting data becomes available (e.g., 240 for 4-hour delay)', examples=[240, 300, 1440], ge=0, ), ] supports_webhooks: Annotated[ bool, - Field(description="Whether this product supports webhook-based reporting notifications"), + Field(description='Whether this product supports webhook-based reporting notifications'), ] timezone: Annotated[ str, Field( description="Timezone for reporting periods. Use 'UTC' or IANA timezone (e.g., 'America/New_York'). Critical for daily/monthly frequency alignment.", - examples=["UTC", "America/New_York", "Europe/London", "America/Los_Angeles"], + examples=['UTC', 'America/New_York', 'Europe/London', 'America/Los_Angeles'], ), ] diff --git a/src/adcp/types/generated_poc/core/reporting_webhook.py b/src/adcp/types/generated_poc/core/reporting_webhook.py new file mode 100644 index 00000000..b1e84e6d --- /dev/null +++ b/src/adcp/types/generated_poc/core/reporting_webhook.py @@ -0,0 +1,70 @@ +# generated by datamodel-codegen: +# filename: core/reporting_webhook.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import AnyUrl, ConfigDict, Field + +from ..enums import auth_scheme, available_metric + + +class Authentication(AdCPBaseModel): + model_config = ConfigDict( + extra='forbid', + ) + credentials: Annotated[ + str, + Field( + description='Credentials for authentication. For Bearer: token sent in Authorization header. For HMAC-SHA256: shared secret used to generate signature. Minimum 32 characters. Exchanged out-of-band during onboarding.', + min_length=32, + ), + ] + schemes: Annotated[ + list[auth_scheme.AuthenticationScheme], + Field( + description="Array of authentication schemes. Supported: ['Bearer'] for simple token auth, ['HMAC-SHA256'] for signature verification (recommended for production)", + max_length=1, + min_length=1, + ), + ] + + +class ReportingFrequency(Enum): + hourly = 'hourly' + daily = 'daily' + monthly = 'monthly' + + +class ReportingWebhook(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + authentication: Annotated[ + Authentication, + Field(description='Authentication configuration for webhook delivery (A2A-compatible)'), + ] + reporting_frequency: Annotated[ + ReportingFrequency, + Field( + description='Frequency for automated reporting delivery. Must be supported by all products in the media buy.' + ), + ] + requested_metrics: Annotated[ + list[available_metric.AvailableMetric] | None, + Field( + description="Optional list of metrics to include in webhook notifications. If omitted, all available metrics are included. Must be subset of product's available_metrics." + ), + ] = None + token: Annotated[ + str | None, + Field( + description='Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.', + min_length=16, + ), + ] = None + url: Annotated[AnyUrl, Field(description='Webhook endpoint URL for reporting notifications')] diff --git a/src/adcp/types/generated_poc/core/response.py b/src/adcp/types/generated_poc/core/response.py index a6bbb32a..e57a47d5 100644 --- a/src/adcp/types/generated_poc/core/response.py +++ b/src/adcp/types/generated_poc/core/response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/response.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,13 +12,13 @@ class ProtocolResponse(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - context_id: Annotated[str | None, Field(description="Session continuity identifier")] = None + context_id: Annotated[str | None, Field(description='Session continuity identifier')] = None data: Annotated[ Any | None, Field( - description="AdCP task-specific response data (see individual task response schemas)" + description='AdCP task-specific response data (see individual task response schemas)' ), ] = None - message: Annotated[str, Field(description="Human-readable summary")] + message: Annotated[str, Field(description='Human-readable summary')] diff --git a/src/adcp/types/generated_poc/core/signal_filters.py b/src/adcp/types/generated_poc/core/signal_filters.py index c16ffcf1..889ca206 100644 --- a/src/adcp/types/generated_poc/core/signal_filters.py +++ b/src/adcp/types/generated_poc/core/signal_filters.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/signal_filters.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,16 +14,16 @@ class SignalFilters(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) catalog_types: Annotated[ list[signal_catalog_type.SignalCatalogType] | None, - Field(description="Filter by catalog type"), + Field(description='Filter by catalog type'), ] = None data_providers: Annotated[ - list[str] | None, Field(description="Filter by specific data providers") + list[str] | None, Field(description='Filter by specific data providers') ] = None - max_cpm: Annotated[float | None, Field(description="Maximum CPM price filter", ge=0.0)] = None + max_cpm: Annotated[float | None, Field(description='Maximum CPM price filter', ge=0.0)] = None min_coverage_percentage: Annotated[ - float | None, Field(description="Minimum coverage requirement", ge=0.0, le=100.0) + float | None, Field(description='Minimum coverage requirement', ge=0.0, le=100.0) ] = None diff --git a/src/adcp/types/generated_poc/core/start_timing.py b/src/adcp/types/generated_poc/core/start_timing.py index eb43ec94..7e7b18c1 100644 --- a/src/adcp/types/generated_poc/core/start_timing.py +++ b/src/adcp/types/generated_poc/core/start_timing.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/start_timing.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -9,10 +9,10 @@ from pydantic import AwareDatetime, Field, RootModel -class StartTiming(RootModel[Literal["asap"] | AwareDatetime]): +class StartTiming(RootModel[Literal['asap'] | AwareDatetime]): root: Annotated[ - Literal["asap"] | AwareDatetime, + Literal['asap'] | AwareDatetime, Field( - description="Campaign start timing: 'asap' or ISO 8601 date-time", title="Start Timing" + description="Campaign start timing: 'asap' or ISO 8601 date-time", title='Start Timing' ), ] diff --git a/src/adcp/types/generated_poc/core/sub_asset.py b/src/adcp/types/generated_poc/core/sub_asset.py index b7c5cab5..91fb5fbe 100644 --- a/src/adcp/types/generated_poc/core/sub_asset.py +++ b/src/adcp/types/generated_poc/core/sub_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/sub_asset.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,45 +12,45 @@ class SubAsset1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) asset_id: Annotated[ - str, Field(description="Unique identifier for the asset within the creative") + str, Field(description='Unique identifier for the asset within the creative') ] asset_kind: Annotated[ - Literal["media"], - Field(description="Discriminator indicating this is a media asset with content_uri"), + Literal['media'], + Field(description='Discriminator indicating this is a media asset with content_uri'), ] asset_type: Annotated[ str, Field( - description="Type of asset. Common types: thumbnail_image, product_image, featured_image, logo" + description='Type of asset. Common types: thumbnail_image, product_image, featured_image, logo' ), ] - content_uri: Annotated[AnyUrl, Field(description="URL for media assets (images, videos, etc.)")] + content_uri: Annotated[AnyUrl, Field(description='URL for media assets (images, videos, etc.)')] class SubAsset2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) asset_id: Annotated[ - str, Field(description="Unique identifier for the asset within the creative") + str, Field(description='Unique identifier for the asset within the creative') ] asset_kind: Annotated[ - Literal["text"], - Field(description="Discriminator indicating this is a text asset with content"), + Literal['text'], + Field(description='Discriminator indicating this is a text asset with content'), ] asset_type: Annotated[ str, Field( - description="Type of asset. Common types: headline, body_text, cta_text, price_text, sponsor_name, author_name, click_url" + description='Type of asset. Common types: headline, body_text, cta_text, price_text, sponsor_name, author_name, click_url' ), ] content: Annotated[ str | list[str], Field( - description="Text content for text-based assets like headlines, body text, CTA text, etc." + description='Text content for text-based assets like headlines, body text, CTA text, etc.' ), ] @@ -59,7 +59,7 @@ class SubAsset(RootModel[SubAsset1 | SubAsset2]): root: Annotated[ SubAsset1 | SubAsset2, Field( - description="Sub-asset for multi-asset creative formats, including carousel images and native ad template variables", - title="Sub-Asset", + description='Sub-asset for multi-asset creative formats, including carousel images and native ad template variables', + title='Sub-Asset', ), ] diff --git a/src/adcp/types/generated_poc/core/targeting.py b/src/adcp/types/generated_poc/core/targeting.py index d9623c42..c2cb0502 100644 --- a/src/adcp/types/generated_poc/core/targeting.py +++ b/src/adcp/types/generated_poc/core/targeting.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/targeting.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -9,45 +9,86 @@ from adcp.types.base import AdCPBaseModel from pydantic import ConfigDict, Field, RootModel +from ..enums import metro_system, postal_system from . import frequency_cap as frequency_cap_1 -class GeoCountryAnyOfItem(RootModel[str]): - root: Annotated[str, Field(pattern="^[A-Z]{2}$")] +class GeoCountry(RootModel[str]): + root: Annotated[str, Field(pattern='^[A-Z]{2}$')] + + +class GeoMetro(AdCPBaseModel): + model_config = ConfigDict( + extra='forbid', + ) + system: Annotated[ + metro_system.MetroAreaSystem, + Field(description="Metro area classification system (e.g., 'nielsen_dma', 'uk_itl2')"), + ] + values: Annotated[ + list[str], + Field( + description="Metro codes within the system (e.g., ['501', '602'] for Nielsen DMAs)", + min_length=1, + ), + ] + + +class GeoPostalArea(AdCPBaseModel): + model_config = ConfigDict( + extra='forbid', + ) + system: Annotated[ + postal_system.PostalCodeSystem, + Field( + description="Postal code system (e.g., 'us_zip', 'gb_outward'). System name encodes country and precision." + ), + ] + values: Annotated[ + list[str], + Field( + description="Postal codes within the system (e.g., ['10001', '10002'] for us_zip)", + min_length=1, + ), + ] + + +class GeoRegion(RootModel[str]): + root: Annotated[str, Field(pattern='^[A-Z]{2}-[A-Z0-9]{1,3}$')] class TargetingOverlay(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) axe_exclude_segment: Annotated[ - str | None, Field(description="AXE segment ID to exclude from targeting") + str | None, Field(description='AXE segment ID to exclude from targeting') ] = None axe_include_segment: Annotated[ - str | None, Field(description="AXE segment ID to include for targeting") + str | None, Field(description='AXE segment ID to include for targeting') ] = None frequency_cap: frequency_cap_1.FrequencyCap | None = None - geo_country_any_of: Annotated[ - list[GeoCountryAnyOfItem] | None, + geo_countries: Annotated[ + list[GeoCountry] | None, Field( - description="Restrict delivery to specific countries (ISO codes). Use for regulatory compliance or RCT testing." + description="Restrict delivery to specific countries. ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE')." ), ] = None - geo_metro_any_of: Annotated[ - list[str] | None, + geo_metros: Annotated[ + list[GeoMetro] | None, Field( - description="Restrict delivery to specific metro areas (DMA codes). Use for regulatory compliance or RCT testing." + description='Restrict delivery to specific metro areas. Each entry specifies the classification system and target values. Seller must declare supported systems in get_adcp_capabilities.' ), ] = None - geo_postal_code_any_of: Annotated[ - list[str] | None, + geo_postal_areas: Annotated[ + list[GeoPostalArea] | None, Field( - description="Restrict delivery to specific postal/ZIP codes. Use for regulatory compliance or RCT testing." + description='Restrict delivery to specific postal areas. Each entry specifies the postal system and target values. Seller must declare supported systems in get_adcp_capabilities.' ), ] = None - geo_region_any_of: Annotated[ - list[str] | None, + geo_regions: Annotated[ + list[GeoRegion] | None, Field( - description="Restrict delivery to specific regions/states. Use for regulatory compliance or RCT testing." + description="Restrict delivery to specific regions/states. ISO 3166-2 subdivision codes (e.g., 'US-CA', 'GB-SCT')." ), ] = None diff --git a/src/adcp/types/generated_poc/creative/list_creative_formats_request.py b/src/adcp/types/generated_poc/creative/list_creative_formats_request.py index 2f99abc3..0dd56089 100644 --- a/src/adcp/types/generated_poc/creative/list_creative_formats_request.py +++ b/src/adcp/types/generated_poc/creative/list_creative_formats_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/list_creative_formats_request.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,25 +16,25 @@ class AssetType(Enum): - image = "image" - video = "video" - audio = "audio" - text = "text" - html = "html" - javascript = "javascript" - url = "url" + image = 'image' + video = 'video' + audio = 'audio' + text = 'text' + html = 'html' + javascript = 'javascript' + url = 'url' class Type(Enum): - audio = "audio" - video = "video" - display = "display" - dooh = "dooh" + audio = 'audio' + video = 'video' + display = 'display' + dooh = 'dooh' class ListCreativeFormatsRequestCreativeAgent(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) asset_types: Annotated[ list[AssetType] | None, @@ -45,44 +45,44 @@ class ListCreativeFormatsRequestCreativeAgent(AdCPBaseModel): context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None format_ids: Annotated[ - list[format_id.FormatId] | None, Field(description="Return only these specific format IDs") + list[format_id.FormatId] | None, Field(description='Return only these specific format IDs') ] = None is_responsive: Annotated[ bool | None, Field( - description="Filter for responsive formats that adapt to container size. When true, returns formats without fixed dimensions." + description='Filter for responsive formats that adapt to container size. When true, returns formats without fixed dimensions.' ), ] = None max_height: Annotated[ int | None, Field( - description="Maximum height in pixels (inclusive). Returns formats with height <= this value. Omit for responsive/fluid formats." + description='Maximum height in pixels (inclusive). Returns formats with height <= this value. Omit for responsive/fluid formats.' ), ] = None max_width: Annotated[ int | None, Field( - description="Maximum width in pixels (inclusive). Returns formats with width <= this value. Omit for responsive/fluid formats." + description='Maximum width in pixels (inclusive). Returns formats with width <= this value. Omit for responsive/fluid formats.' ), ] = None min_height: Annotated[ int | None, Field( - description="Minimum height in pixels (inclusive). Returns formats with height >= this value." + description='Minimum height in pixels (inclusive). Returns formats with height >= this value.' ), ] = None min_width: Annotated[ int | None, Field( - description="Minimum width in pixels (inclusive). Returns formats with width >= this value." + description='Minimum width in pixels (inclusive). Returns formats with width >= this value.' ), ] = None name_search: Annotated[ - str | None, Field(description="Search for formats by name (case-insensitive partial match)") + str | None, Field(description='Search for formats by name (case-insensitive partial match)') ] = None type: Annotated[ Type | None, Field( - description="Filter by format type (technical categories with distinct requirements)" + description='Filter by format type (technical categories with distinct requirements)' ), ] = None diff --git a/src/adcp/types/generated_poc/creative/list_creative_formats_response.py b/src/adcp/types/generated_poc/creative/list_creative_formats_response.py index ddb7b6d5..b24c93ec 100644 --- a/src/adcp/types/generated_poc/creative/list_creative_formats_response.py +++ b/src/adcp/types/generated_poc/creative/list_creative_formats_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/list_creative_formats_response.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -18,7 +18,7 @@ class CreativeAgent(AdCPBaseModel): agent_name: Annotated[ - str | None, Field(description="Human-readable name for the creative agent") + str | None, Field(description='Human-readable name for the creative agent') ] = None agent_url: Annotated[ AnyUrl, @@ -28,23 +28,23 @@ class CreativeAgent(AdCPBaseModel): ] capabilities: Annotated[ list[creative_agent_capability.CreativeAgentCapability] | None, - Field(description="Capabilities this creative agent provides"), + Field(description='Capabilities this creative agent provides'), ] = None class ListCreativeFormatsResponseCreativeAgent(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None creative_agents: Annotated[ list[CreativeAgent] | None, Field( - description="Optional: Creative agents that provide additional formats. Buyers can recursively query these agents to discover more formats. No authentication required for list_creative_formats." + description='Optional: Creative agents that provide additional formats. Buyers can recursively query these agents to discover more formats. No authentication required for list_creative_formats.' ), ] = None errors: Annotated[ - list[error.Error] | None, Field(description="Task-specific errors and warnings") + list[error.Error] | None, Field(description='Task-specific errors and warnings') ] = None ext: ext_1.ExtensionObject | None = None formats: Annotated[ diff --git a/src/adcp/types/generated_poc/creative/preview_creative_request.py b/src/adcp/types/generated_poc/creative/preview_creative_request.py index a685d7a7..65580255 100644 --- a/src/adcp/types/generated_poc/creative/preview_creative_request.py +++ b/src/adcp/types/generated_poc/creative/preview_creative_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/preview_creative_request.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -18,7 +18,7 @@ class Input(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context_description: Annotated[ str | None, @@ -42,37 +42,37 @@ class Input(AdCPBaseModel): class Input2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context_description: Annotated[ str | None, - Field(description="Natural language description of the context for AI-generated content"), + Field(description='Natural language description of the context for AI-generated content'), ] = None macros: Annotated[ - dict[str, str] | None, Field(description="Macro values to use for this preview") + dict[str, str] | None, Field(description='Macro values to use for this preview') ] = None - name: Annotated[str, Field(description="Human-readable name for this input set")] + name: Annotated[str, Field(description='Human-readable name for this input set')] class PreviewCreativeRequest1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None creative_manifest: Annotated[ creative_manifest_1.CreativeManifest, Field( - description="Complete creative manifest with all required assets (including promoted_offerings if required by the format)" + description='Complete creative manifest with all required assets (including promoted_offerings if required by the format)' ), ] ext: ext_1.ExtensionObject | None = None format_id: Annotated[ - format_id_1.FormatId, Field(description="Format identifier for rendering the preview") + format_id_1.FormatId, Field(description='Format identifier for rendering the preview') ] inputs: Annotated[ list[Input] | None, Field( - description="Array of input sets for generating multiple preview variants. Each input set defines macros and context values for one preview rendering. If not provided, creative agent will generate default previews." + description='Array of input sets for generating multiple preview variants. Each input set defines macros and context values for one preview rendering. If not provided, creative agent will generate default previews.' ), ] = None output_format: Annotated[ @@ -82,28 +82,28 @@ class PreviewCreativeRequest1(AdCPBaseModel): ), ] = preview_output_format.PreviewOutputFormat.url request_type: Annotated[ - Literal["single"], - Field(description="Discriminator indicating this is a single preview request"), + Literal['single'], + Field(description='Discriminator indicating this is a single preview request'), ] template_id: Annotated[ - str | None, Field(description="Specific template ID for custom format rendering") + str | None, Field(description='Specific template ID for custom format rendering') ] = None class Request(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) creative_manifest: Annotated[ creative_manifest_1.CreativeManifest, - Field(description="Complete creative manifest with all required assets"), + Field(description='Complete creative manifest with all required assets'), ] format_id: Annotated[ - format_id_1.FormatId, Field(description="Format identifier for rendering the preview") + format_id_1.FormatId, Field(description='Format identifier for rendering the preview') ] inputs: Annotated[ list[Input2] | None, - Field(description="Array of input sets for generating multiple preview variants"), + Field(description='Array of input sets for generating multiple preview variants'), ] = None output_format: Annotated[ preview_output_format.PreviewOutputFormat | None, @@ -112,13 +112,13 @@ class Request(AdCPBaseModel): ), ] = preview_output_format.PreviewOutputFormat.url template_id: Annotated[ - str | None, Field(description="Specific template ID for custom format rendering") + str | None, Field(description='Specific template ID for custom format rendering') ] = None class PreviewCreativeRequest2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None @@ -129,13 +129,13 @@ class PreviewCreativeRequest2(AdCPBaseModel): ), ] = preview_output_format.PreviewOutputFormat.url request_type: Annotated[ - Literal["batch"], - Field(description="Discriminator indicating this is a batch preview request"), + Literal['batch'], + Field(description='Discriminator indicating this is a batch preview request'), ] requests: Annotated[ list[Request], Field( - description="Array of preview requests (1-50 items). Each follows the single request structure.", + description='Array of preview requests (1-50 items). Each follows the single request structure.', max_length=50, min_length=1, ), @@ -146,8 +146,8 @@ class PreviewCreativeRequest(RootModel[PreviewCreativeRequest1 | PreviewCreative root: Annotated[ PreviewCreativeRequest1 | PreviewCreativeRequest2, Field( - discriminator="request_type", - description="Request to generate previews of one or more creative manifests. Accepts either a single creative request or an array of requests for batch processing.", - title="Preview Creative Request", + discriminator='request_type', + description='Request to generate previews of one or more creative manifests. Accepts either a single creative request or an array of requests for batch processing.', + title='Preview Creative Request', ), ] diff --git a/src/adcp/types/generated_poc/creative/preview_creative_response.py b/src/adcp/types/generated_poc/creative/preview_creative_response.py index e78e0909..10fc2f32 100644 --- a/src/adcp/types/generated_poc/creative/preview_creative_response.py +++ b/src/adcp/types/generated_poc/creative/preview_creative_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/preview_creative_response.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,12 +16,12 @@ class Input(AdCPBaseModel): context_description: Annotated[ - str | None, Field(description="Context description applied to this variant") + str | None, Field(description='Context description applied to this variant') ] = None macros: Annotated[ - dict[str, str] | None, Field(description="Macro values applied to this variant") + dict[str, str] | None, Field(description='Macro values applied to this variant') ] = None - name: Annotated[str, Field(description="Human-readable name for this variant")] + name: Annotated[str, Field(description='Human-readable name for this variant')] class Error(AdCPBaseModel): @@ -31,8 +31,8 @@ class Error(AdCPBaseModel): description="Error code (e.g., 'invalid_manifest', 'unsupported_format', 'missing_assets')" ), ] - details: Annotated[dict[str, Any] | None, Field(description="Additional error context")] = None - message: Annotated[str, Field(description="Human-readable error message")] + details: Annotated[dict[str, Any] | None, Field(description='Additional error context')] = None + message: Annotated[str, Field(description='Human-readable error message')] class Input4(AdCPBaseModel): @@ -45,14 +45,14 @@ class Preview(AdCPBaseModel): input: Annotated[ Input, Field( - description="The input parameters that generated this preview variant. Echoes back the request input or shows defaults used." + description='The input parameters that generated this preview variant. Echoes back the request input or shows defaults used.' ), ] - preview_id: Annotated[str, Field(description="Unique identifier for this preview variant")] + preview_id: Annotated[str, Field(description='Unique identifier for this preview variant')] renders: Annotated[ list[preview_render.PreviewRender], Field( - description="Array of rendered pieces for this preview variant. Most formats render as a single piece. Companion ad formats (video + banner), multi-placement formats, and adaptive formats render as multiple pieces.", + description='Array of rendered pieces for this preview variant. Most formats render as a single piece. Companion ad formats (video + banner), multi-placement formats, and adaptive formats render as multiple pieces.', min_length=1, ), ] @@ -60,29 +60,29 @@ class Preview(AdCPBaseModel): class PreviewCreativeResponse1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None expires_at: Annotated[ - AwareDatetime, Field(description="ISO 8601 timestamp when preview links expire") + AwareDatetime, Field(description='ISO 8601 timestamp when preview links expire') ] ext: ext_1.ExtensionObject | None = None interactive_url: Annotated[ AnyUrl | None, Field( - description="Optional URL to an interactive testing page that shows all preview variants with controls to switch between them, modify macro values, and test different scenarios." + description='Optional URL to an interactive testing page that shows all preview variants with controls to switch between them, modify macro values, and test different scenarios.' ), ] = None previews: Annotated[ list[Preview], Field( - description="Array of preview variants. Each preview corresponds to an input set from the request. If no inputs were provided, returns a single default preview.", + description='Array of preview variants. Each preview corresponds to an input set from the request. If no inputs were provided, returns a single default preview.', min_length=1, ), ] response_type: Annotated[ - Literal["single"], - Field(description="Discriminator indicating this is a single preview response"), + Literal['single'], + Field(description='Discriminator indicating this is a single preview response'), ] @@ -97,16 +97,16 @@ class Response(AdCPBaseModel): interactive_url: AnyUrl | None = None previews: Annotated[ list[Preview1], - Field(description="Array of preview variants for this creative", min_length=1), + Field(description='Array of preview variants for this creative', min_length=1), ] class Results(AdCPBaseModel): - error: Annotated[Error | None, Field(description="Error information for failed requests")] = ( + error: Annotated[Error | None, Field(description='Error information for failed requests')] = ( None ) - response: Annotated[Response, Field(description="Preview response for successful requests")] - success: Annotated[Literal[True], Field(description="Whether this preview request succeeded")] + response: Annotated[Response, Field(description='Preview response for successful requests')] + success: Annotated[Literal[True], Field(description='Whether this preview request succeeded')] class Preview2(Preview1): @@ -118,32 +118,32 @@ class Response1(AdCPBaseModel): interactive_url: AnyUrl | None = None previews: Annotated[ list[Preview2], - Field(description="Array of preview variants for this creative", min_length=1), + Field(description='Array of preview variants for this creative', min_length=1), ] class Results1(AdCPBaseModel): - error: Annotated[Error, Field(description="Error information for failed requests")] + error: Annotated[Error, Field(description='Error information for failed requests')] response: Annotated[ - Response1 | None, Field(description="Preview response for successful requests") + Response1 | None, Field(description='Preview response for successful requests') ] = None - success: Annotated[Literal[False], Field(description="Whether this preview request succeeded")] + success: Annotated[Literal[False], Field(description='Whether this preview request succeeded')] class PreviewCreativeResponse2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None response_type: Annotated[ - Literal["batch"], - Field(description="Discriminator indicating this is a batch preview response"), + Literal['batch'], + Field(description='Discriminator indicating this is a batch preview response'), ] results: Annotated[ list[Results | Results1], Field( - description="Array of preview results corresponding to each request in the same order. results[0] is the result for requests[0], results[1] for requests[1], etc. Order is guaranteed even when some requests fail. Each result contains either a successful preview response or an error.", + description='Array of preview results corresponding to each request in the same order. results[0] is the result for requests[0], results[1] for requests[1], etc. Order is guaranteed even when some requests fail. Each result contains either a successful preview response or an error.', min_length=1, ), ] @@ -153,7 +153,7 @@ class PreviewCreativeResponse(RootModel[PreviewCreativeResponse1 | PreviewCreati root: Annotated[ PreviewCreativeResponse1 | PreviewCreativeResponse2, Field( - description="Response containing preview links for one or more creatives. Format matches the request: single preview response for single requests, batch results for batch requests.", - title="Preview Creative Response", + description='Response containing preview links for one or more creatives. Format matches the request: single preview response for single requests, batch results for batch requests.', + title='Preview Creative Response', ), ] diff --git a/src/adcp/types/generated_poc/creative/preview_render.py b/src/adcp/types/generated_poc/creative/preview_render.py index 1a19ba57..19e4247b 100644 --- a/src/adcp/types/generated_poc/creative/preview_render.py +++ b/src/adcp/types/generated_poc/creative/preview_render.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/preview_render.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class Dimensions(AdCPBaseModel): class Embedding(AdCPBaseModel): csp_policy: Annotated[ - str | None, Field(description="Content Security Policy requirements for embedding") + str | None, Field(description='Content Security Policy requirements for embedding') ] = None recommended_sandbox: Annotated[ str | None, @@ -26,35 +26,35 @@ class Embedding(AdCPBaseModel): ), ] = None requires_https: Annotated[ - bool | None, Field(description="Whether this output requires HTTPS for secure embedding") + bool | None, Field(description='Whether this output requires HTTPS for secure embedding') ] = None supports_fullscreen: Annotated[ - bool | None, Field(description="Whether this output supports fullscreen mode") + bool | None, Field(description='Whether this output supports fullscreen mode') ] = None class PreviewRender1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) dimensions: Annotated[ - Dimensions | None, Field(description="Dimensions for this rendered piece") + Dimensions | None, Field(description='Dimensions for this rendered piece') ] = None embedding: Annotated[ Embedding | None, - Field(description="Optional security and embedding metadata for safe iframe integration"), + Field(description='Optional security and embedding metadata for safe iframe integration'), ] = None output_format: Annotated[ - Literal["url"], Field(description="Discriminator indicating preview_url is provided") + Literal['url'], Field(description='Discriminator indicating preview_url is provided') ] preview_url: Annotated[ AnyUrl, Field( - description="URL to an HTML page that renders this piece. Can be embedded in an iframe." + description='URL to an HTML page that renders this piece. Can be embedded in an iframe.' ), ] render_id: Annotated[ - str, Field(description="Unique identifier for this rendered piece within the variant") + str, Field(description='Unique identifier for this rendered piece within the variant') ] role: Annotated[ str, @@ -66,25 +66,25 @@ class PreviewRender1(AdCPBaseModel): class PreviewRender2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) dimensions: Annotated[ - Dimensions | None, Field(description="Dimensions for this rendered piece") + Dimensions | None, Field(description='Dimensions for this rendered piece') ] = None embedding: Annotated[ - Embedding | None, Field(description="Optional security and embedding metadata") + Embedding | None, Field(description='Optional security and embedding metadata') ] = None output_format: Annotated[ - Literal["html"], Field(description="Discriminator indicating preview_html is provided") + Literal['html'], Field(description='Discriminator indicating preview_html is provided') ] preview_html: Annotated[ str, Field( - description="Raw HTML for this rendered piece. Can be embedded directly in the page without iframe. Security warning: Only use with trusted creative agents as this bypasses iframe sandboxing." + description='Raw HTML for this rendered piece. Can be embedded directly in the page without iframe. Security warning: Only use with trusted creative agents as this bypasses iframe sandboxing.' ), ] render_id: Annotated[ - str, Field(description="Unique identifier for this rendered piece within the variant") + str, Field(description='Unique identifier for this rendered piece within the variant') ] role: Annotated[ str, @@ -96,35 +96,35 @@ class PreviewRender2(AdCPBaseModel): class PreviewRender3(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) dimensions: Annotated[ - Dimensions | None, Field(description="Dimensions for this rendered piece") + Dimensions | None, Field(description='Dimensions for this rendered piece') ] = None embedding: Annotated[ Embedding | None, - Field(description="Optional security and embedding metadata for safe iframe integration"), + Field(description='Optional security and embedding metadata for safe iframe integration'), ] = None output_format: Annotated[ - Literal["both"], + Literal['both'], Field( - description="Discriminator indicating both preview_url and preview_html are provided" + description='Discriminator indicating both preview_url and preview_html are provided' ), ] preview_html: Annotated[ str, Field( - description="Raw HTML for this rendered piece. Can be embedded directly in the page without iframe. Security warning: Only use with trusted creative agents as this bypasses iframe sandboxing." + description='Raw HTML for this rendered piece. Can be embedded directly in the page without iframe. Security warning: Only use with trusted creative agents as this bypasses iframe sandboxing.' ), ] preview_url: Annotated[ AnyUrl, Field( - description="URL to an HTML page that renders this piece. Can be embedded in an iframe." + description='URL to an HTML page that renders this piece. Can be embedded in an iframe.' ), ] render_id: Annotated[ - str, Field(description="Unique identifier for this rendered piece within the variant") + str, Field(description='Unique identifier for this rendered piece within the variant') ] role: Annotated[ str, @@ -138,7 +138,7 @@ class PreviewRender(RootModel[PreviewRender1 | PreviewRender2 | PreviewRender3]) root: Annotated[ PreviewRender1 | PreviewRender2 | PreviewRender3, Field( - description="A single rendered piece of a creative preview with discriminated output format", - title="Preview Render", + description='A single rendered piece of a creative preview with discriminated output format', + title='Preview Render', ), ] diff --git a/src/adcp/types/generated_poc/enums/adcp_domain.py b/src/adcp/types/generated_poc/enums/adcp_domain.py index e736171a..9a7f507b 100644 --- a/src/adcp/types/generated_poc/enums/adcp_domain.py +++ b/src/adcp/types/generated_poc/enums/adcp_domain.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/adcp_domain.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,7 +8,7 @@ class AdcpDomain(Enum): - media_buy = "media-buy" - signals = "signals" - governance = "governance" - creative = "creative" + media_buy = 'media-buy' + signals = 'signals' + governance = 'governance' + creative = 'creative' diff --git a/src/adcp/types/generated_poc/enums/asset_content_type.py b/src/adcp/types/generated_poc/enums/asset_content_type.py index b1c57669..9a232e22 100644 --- a/src/adcp/types/generated_poc/enums/asset_content_type.py +++ b/src/adcp/types/generated_poc/enums/asset_content_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/asset_content_type.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,16 +8,16 @@ class AssetContentType(Enum): - image = "image" - video = "video" - audio = "audio" - text = "text" - markdown = "markdown" - html = "html" - css = "css" - javascript = "javascript" - vast = "vast" - daast = "daast" - promoted_offerings = "promoted_offerings" - url = "url" - webhook = "webhook" + image = 'image' + video = 'video' + audio = 'audio' + text = 'text' + markdown = 'markdown' + html = 'html' + css = 'css' + javascript = 'javascript' + vast = 'vast' + daast = 'daast' + promoted_offerings = 'promoted_offerings' + url = 'url' + webhook = 'webhook' diff --git a/src/adcp/types/generated_poc/enums/auth_scheme.py b/src/adcp/types/generated_poc/enums/auth_scheme.py index b4bfac14..3c923c1a 100644 --- a/src/adcp/types/generated_poc/enums/auth_scheme.py +++ b/src/adcp/types/generated_poc/enums/auth_scheme.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/auth_scheme.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,5 +8,5 @@ class AuthenticationScheme(Enum): - Bearer = "Bearer" - HMAC_SHA256 = "HMAC-SHA256" + Bearer = 'Bearer' + HMAC_SHA256 = 'HMAC-SHA256' diff --git a/src/adcp/types/generated_poc/enums/available_metric.py b/src/adcp/types/generated_poc/enums/available_metric.py index 36365c5b..1705630b 100644 --- a/src/adcp/types/generated_poc/enums/available_metric.py +++ b/src/adcp/types/generated_poc/enums/available_metric.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/available_metric.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,12 +8,12 @@ class AvailableMetric(Enum): - impressions = "impressions" - spend = "spend" - clicks = "clicks" - ctr = "ctr" - video_completions = "video_completions" - completion_rate = "completion_rate" - conversions = "conversions" - viewability = "viewability" - engagement_rate = "engagement_rate" + impressions = 'impressions' + spend = 'spend' + clicks = 'clicks' + ctr = 'ctr' + video_completions = 'video_completions' + completion_rate = 'completion_rate' + conversions = 'conversions' + viewability = 'viewability' + engagement_rate = 'engagement_rate' diff --git a/src/adcp/types/generated_poc/enums/channels.py b/src/adcp/types/generated_poc/enums/channels.py index 82f32a1c..e1bddf94 100644 --- a/src/adcp/types/generated_poc/enums/channels.py +++ b/src/adcp/types/generated_poc/enums/channels.py @@ -1,19 +1,29 @@ # generated by datamodel-codegen: # filename: enums/channels.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations from enum import Enum -class AdvertisingChannels(Enum): - display = "display" - video = "video" - audio = "audio" - native = "native" - dooh = "dooh" - ctv = "ctv" - podcast = "podcast" - retail = "retail" - social = "social" +class MediaChannel(Enum): + display = 'display' + olv = 'olv' + social = 'social' + search = 'search' + ctv = 'ctv' + linear_tv = 'linear_tv' + radio = 'radio' + streaming_audio = 'streaming_audio' + podcast = 'podcast' + dooh = 'dooh' + ooh = 'ooh' + print = 'print' + cinema = 'cinema' + email = 'email' + gaming = 'gaming' + retail_media = 'retail_media' + influencer = 'influencer' + affiliate = 'affiliate' + product_placement = 'product_placement' diff --git a/src/adcp/types/generated_poc/enums/co_branding_requirement.py b/src/adcp/types/generated_poc/enums/co_branding_requirement.py index b959ac6d..903e6fc2 100644 --- a/src/adcp/types/generated_poc/enums/co_branding_requirement.py +++ b/src/adcp/types/generated_poc/enums/co_branding_requirement.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/co_branding_requirement.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,6 +8,6 @@ class CoBrandingRequirement(Enum): - required = "required" - optional = "optional" - none = "none" + required = 'required' + optional = 'optional' + none = 'none' diff --git a/src/adcp/types/generated_poc/enums/creative_action.py b/src/adcp/types/generated_poc/enums/creative_action.py index 535ba3f4..4e100b97 100644 --- a/src/adcp/types/generated_poc/enums/creative_action.py +++ b/src/adcp/types/generated_poc/enums/creative_action.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/creative_action.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,8 +8,8 @@ class CreativeAction(Enum): - created = "created" - updated = "updated" - unchanged = "unchanged" - failed = "failed" - deleted = "deleted" + created = 'created' + updated = 'updated' + unchanged = 'unchanged' + failed = 'failed' + deleted = 'deleted' diff --git a/src/adcp/types/generated_poc/enums/creative_agent_capability.py b/src/adcp/types/generated_poc/enums/creative_agent_capability.py index 444595f1..5c1c2ebb 100644 --- a/src/adcp/types/generated_poc/enums/creative_agent_capability.py +++ b/src/adcp/types/generated_poc/enums/creative_agent_capability.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/creative_agent_capability.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,7 +8,7 @@ class CreativeAgentCapability(Enum): - validation = "validation" - assembly = "assembly" - generation = "generation" - preview = "preview" + validation = 'validation' + assembly = 'assembly' + generation = 'generation' + preview = 'preview' diff --git a/src/adcp/types/generated_poc/enums/creative_sort_field.py b/src/adcp/types/generated_poc/enums/creative_sort_field.py index b42ffb46..92b5ea29 100644 --- a/src/adcp/types/generated_poc/enums/creative_sort_field.py +++ b/src/adcp/types/generated_poc/enums/creative_sort_field.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/creative_sort_field.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,9 +8,9 @@ class CreativeSortField(Enum): - created_date = "created_date" - updated_date = "updated_date" - name = "name" - status = "status" - assignment_count = "assignment_count" - performance_score = "performance_score" + created_date = 'created_date' + updated_date = 'updated_date' + name = 'name' + status = 'status' + assignment_count = 'assignment_count' + performance_score = 'performance_score' diff --git a/src/adcp/types/generated_poc/enums/creative_status.py b/src/adcp/types/generated_poc/enums/creative_status.py index 227c0755..b9dc2acf 100644 --- a/src/adcp/types/generated_poc/enums/creative_status.py +++ b/src/adcp/types/generated_poc/enums/creative_status.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/creative_status.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,7 +8,8 @@ class CreativeStatus(Enum): - processing = "processing" - approved = "approved" - rejected = "rejected" - pending_review = "pending_review" + processing = 'processing' + approved = 'approved' + rejected = 'rejected' + pending_review = 'pending_review' + archived = 'archived' diff --git a/src/adcp/types/generated_poc/enums/daast_tracking_event.py b/src/adcp/types/generated_poc/enums/daast_tracking_event.py index a9caa261..7bb8f5d7 100644 --- a/src/adcp/types/generated_poc/enums/daast_tracking_event.py +++ b/src/adcp/types/generated_poc/enums/daast_tracking_event.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/daast_tracking_event.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,14 +8,14 @@ class DaastTrackingEvent(Enum): - start = "start" - firstQuartile = "firstQuartile" - midpoint = "midpoint" - thirdQuartile = "thirdQuartile" - complete = "complete" - impression = "impression" - pause = "pause" - resume = "resume" - skip = "skip" - mute = "mute" - unmute = "unmute" + start = 'start' + firstQuartile = 'firstQuartile' + midpoint = 'midpoint' + thirdQuartile = 'thirdQuartile' + complete = 'complete' + impression = 'impression' + pause = 'pause' + resume = 'resume' + skip = 'skip' + mute = 'mute' + unmute = 'unmute' diff --git a/src/adcp/types/generated_poc/enums/daast_version.py b/src/adcp/types/generated_poc/enums/daast_version.py index 5f07de29..49d70d70 100644 --- a/src/adcp/types/generated_poc/enums/daast_version.py +++ b/src/adcp/types/generated_poc/enums/daast_version.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/daast_version.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,5 +8,5 @@ class DaastVersion(Enum): - field_1_0 = "1.0" - field_1_1 = "1.1" + field_1_0 = '1.0' + field_1_1 = '1.1' diff --git a/src/adcp/types/generated_poc/enums/delivery_type.py b/src/adcp/types/generated_poc/enums/delivery_type.py index f2b48f80..6a3e1573 100644 --- a/src/adcp/types/generated_poc/enums/delivery_type.py +++ b/src/adcp/types/generated_poc/enums/delivery_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/delivery_type.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,5 +8,5 @@ class DeliveryType(Enum): - guaranteed = "guaranteed" - non_guaranteed = "non_guaranteed" + guaranteed = 'guaranteed' + non_guaranteed = 'non_guaranteed' diff --git a/src/adcp/types/generated_poc/enums/dimension_unit.py b/src/adcp/types/generated_poc/enums/dimension_unit.py index 714afd26..944b4335 100644 --- a/src/adcp/types/generated_poc/enums/dimension_unit.py +++ b/src/adcp/types/generated_poc/enums/dimension_unit.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/dimension_unit.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,7 +8,7 @@ class DimensionUnit(Enum): - px = "px" - dp = "dp" - inches = "inches" - cm = "cm" + px = 'px' + dp = 'dp' + inches = 'inches' + cm = 'cm' diff --git a/src/adcp/types/generated_poc/enums/feed_format.py b/src/adcp/types/generated_poc/enums/feed_format.py index da7f5e1e..daacb13d 100644 --- a/src/adcp/types/generated_poc/enums/feed_format.py +++ b/src/adcp/types/generated_poc/enums/feed_format.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/feed_format.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,6 +8,6 @@ class FeedFormat(Enum): - google_merchant_center = "google_merchant_center" - facebook_catalog = "facebook_catalog" - custom = "custom" + google_merchant_center = 'google_merchant_center' + facebook_catalog = 'facebook_catalog' + custom = 'custom' diff --git a/src/adcp/types/generated_poc/enums/feedback_source.py b/src/adcp/types/generated_poc/enums/feedback_source.py index 6027078a..5bb4e078 100644 --- a/src/adcp/types/generated_poc/enums/feedback_source.py +++ b/src/adcp/types/generated_poc/enums/feedback_source.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/feedback_source.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,7 +8,7 @@ class FeedbackSource(Enum): - buyer_attribution = "buyer_attribution" - third_party_measurement = "third_party_measurement" - platform_analytics = "platform_analytics" - verification_partner = "verification_partner" + buyer_attribution = 'buyer_attribution' + third_party_measurement = 'third_party_measurement' + platform_analytics = 'platform_analytics' + verification_partner = 'verification_partner' diff --git a/src/adcp/types/generated_poc/enums/format_category.py b/src/adcp/types/generated_poc/enums/format_category.py index da0d4d9f..0a9846e1 100644 --- a/src/adcp/types/generated_poc/enums/format_category.py +++ b/src/adcp/types/generated_poc/enums/format_category.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/format_category.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,10 +8,10 @@ class FormatCategory(Enum): - audio = "audio" - video = "video" - display = "display" - native = "native" - dooh = "dooh" - rich_media = "rich_media" - universal = "universal" + audio = 'audio' + video = 'video' + display = 'display' + native = 'native' + dooh = 'dooh' + rich_media = 'rich_media' + universal = 'universal' diff --git a/src/adcp/types/generated_poc/enums/format_id_parameter.py b/src/adcp/types/generated_poc/enums/format_id_parameter.py index dd3f1cdb..3d35a9b4 100644 --- a/src/adcp/types/generated_poc/enums/format_id_parameter.py +++ b/src/adcp/types/generated_poc/enums/format_id_parameter.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/format_id_parameter.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,5 +8,5 @@ class FormatIdParameter(Enum): - dimensions = "dimensions" - duration = "duration" + dimensions = 'dimensions' + duration = 'duration' diff --git a/src/adcp/types/generated_poc/enums/frequency_cap_scope.py b/src/adcp/types/generated_poc/enums/frequency_cap_scope.py index fe91d391..ea329f6a 100644 --- a/src/adcp/types/generated_poc/enums/frequency_cap_scope.py +++ b/src/adcp/types/generated_poc/enums/frequency_cap_scope.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/frequency_cap_scope.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -9,8 +9,8 @@ from pydantic import Field, RootModel -class FrequencyCapScope(RootModel[Literal["package"]]): +class FrequencyCapScope(RootModel[Literal['package']]): root: Annotated[ - Literal["package"], - Field(description="Scope for frequency cap application", title="Frequency Cap Scope"), + Literal['package'], + Field(description='Scope for frequency cap application', title='Frequency Cap Scope'), ] diff --git a/src/adcp/types/generated_poc/enums/geo_level.py b/src/adcp/types/generated_poc/enums/geo_level.py new file mode 100644 index 00000000..5126471a --- /dev/null +++ b/src/adcp/types/generated_poc/enums/geo_level.py @@ -0,0 +1,14 @@ +# generated by datamodel-codegen: +# filename: enums/geo_level.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum + + +class GeographicTargetingLevel(Enum): + country = 'country' + region = 'region' + metro = 'metro' + postal_area = 'postal_area' diff --git a/src/adcp/types/generated_poc/enums/history_entry_type.py b/src/adcp/types/generated_poc/enums/history_entry_type.py index e628d2d1..da6d069e 100644 --- a/src/adcp/types/generated_poc/enums/history_entry_type.py +++ b/src/adcp/types/generated_poc/enums/history_entry_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/history_entry_type.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,5 +8,5 @@ class HistoryEntryType(Enum): - request = "request" - response = "response" + request = 'request' + response = 'response' diff --git a/src/adcp/types/generated_poc/enums/http_method.py b/src/adcp/types/generated_poc/enums/http_method.py index 165725e4..ec0e0b23 100644 --- a/src/adcp/types/generated_poc/enums/http_method.py +++ b/src/adcp/types/generated_poc/enums/http_method.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/http_method.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,5 +8,5 @@ class HttpMethod(Enum): - GET = "GET" - POST = "POST" + GET = 'GET' + POST = 'POST' diff --git a/src/adcp/types/generated_poc/enums/identifier_types.py b/src/adcp/types/generated_poc/enums/identifier_types.py index 8bd44883..9e41e287 100644 --- a/src/adcp/types/generated_poc/enums/identifier_types.py +++ b/src/adcp/types/generated_poc/enums/identifier_types.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/identifier_types.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,22 +8,22 @@ class PropertyIdentifierTypes(Enum): - domain = "domain" - subdomain = "subdomain" - network_id = "network_id" - ios_bundle = "ios_bundle" - android_package = "android_package" - apple_app_store_id = "apple_app_store_id" - google_play_id = "google_play_id" - roku_store_id = "roku_store_id" - fire_tv_asin = "fire_tv_asin" - samsung_app_id = "samsung_app_id" - apple_tv_bundle = "apple_tv_bundle" - bundle_id = "bundle_id" - venue_id = "venue_id" - screen_id = "screen_id" - openooh_venue_type = "openooh_venue_type" - rss_url = "rss_url" - apple_podcast_id = "apple_podcast_id" - spotify_show_id = "spotify_show_id" - podcast_guid = "podcast_guid" + domain = 'domain' + subdomain = 'subdomain' + network_id = 'network_id' + ios_bundle = 'ios_bundle' + android_package = 'android_package' + apple_app_store_id = 'apple_app_store_id' + google_play_id = 'google_play_id' + roku_store_id = 'roku_store_id' + fire_tv_asin = 'fire_tv_asin' + samsung_app_id = 'samsung_app_id' + apple_tv_bundle = 'apple_tv_bundle' + bundle_id = 'bundle_id' + venue_id = 'venue_id' + screen_id = 'screen_id' + openooh_venue_type = 'openooh_venue_type' + rss_url = 'rss_url' + apple_podcast_id = 'apple_podcast_id' + spotify_show_id = 'spotify_show_id' + podcast_guid = 'podcast_guid' diff --git a/src/adcp/types/generated_poc/enums/javascript_module_type.py b/src/adcp/types/generated_poc/enums/javascript_module_type.py index e03b4b6c..230b4062 100644 --- a/src/adcp/types/generated_poc/enums/javascript_module_type.py +++ b/src/adcp/types/generated_poc/enums/javascript_module_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/javascript_module_type.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,6 +8,6 @@ class JavascriptModuleType(Enum): - esm = "esm" - commonjs = "commonjs" - script = "script" + esm = 'esm' + commonjs = 'commonjs' + script = 'script' diff --git a/src/adcp/types/generated_poc/enums/landing_page_requirement.py b/src/adcp/types/generated_poc/enums/landing_page_requirement.py index 7751357a..fdbc29c7 100644 --- a/src/adcp/types/generated_poc/enums/landing_page_requirement.py +++ b/src/adcp/types/generated_poc/enums/landing_page_requirement.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/landing_page_requirement.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,6 +8,6 @@ class LandingPageRequirement(Enum): - any = "any" - retailer_site_only = "retailer_site_only" - must_include_retailer = "must_include_retailer" + any = 'any' + retailer_site_only = 'retailer_site_only' + must_include_retailer = 'must_include_retailer' diff --git a/src/adcp/types/generated_poc/enums/markdown_flavor.py b/src/adcp/types/generated_poc/enums/markdown_flavor.py index 84b7ca25..e7af3602 100644 --- a/src/adcp/types/generated_poc/enums/markdown_flavor.py +++ b/src/adcp/types/generated_poc/enums/markdown_flavor.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/markdown_flavor.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,5 +8,5 @@ class MarkdownFlavor(Enum): - commonmark = "commonmark" - gfm = "gfm" + commonmark = 'commonmark' + gfm = 'gfm' diff --git a/src/adcp/types/generated_poc/enums/media_buy_status.py b/src/adcp/types/generated_poc/enums/media_buy_status.py index 463ff984..e9e389b1 100644 --- a/src/adcp/types/generated_poc/enums/media_buy_status.py +++ b/src/adcp/types/generated_poc/enums/media_buy_status.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/media_buy_status.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,7 +8,7 @@ class MediaBuyStatus(Enum): - pending_activation = "pending_activation" - active = "active" - paused = "paused" - completed = "completed" + pending_activation = 'pending_activation' + active = 'active' + paused = 'paused' + completed = 'completed' diff --git a/src/adcp/types/generated_poc/enums/metric_type.py b/src/adcp/types/generated_poc/enums/metric_type.py index 053b9616..b65ce1ce 100644 --- a/src/adcp/types/generated_poc/enums/metric_type.py +++ b/src/adcp/types/generated_poc/enums/metric_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/metric_type.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,11 +8,11 @@ class MetricType(Enum): - overall_performance = "overall_performance" - conversion_rate = "conversion_rate" - brand_lift = "brand_lift" - click_through_rate = "click_through_rate" - completion_rate = "completion_rate" - viewability = "viewability" - brand_safety = "brand_safety" - cost_efficiency = "cost_efficiency" + overall_performance = 'overall_performance' + conversion_rate = 'conversion_rate' + brand_lift = 'brand_lift' + click_through_rate = 'click_through_rate' + completion_rate = 'completion_rate' + viewability = 'viewability' + brand_safety = 'brand_safety' + cost_efficiency = 'cost_efficiency' diff --git a/src/adcp/types/generated_poc/enums/metro_system.py b/src/adcp/types/generated_poc/enums/metro_system.py new file mode 100644 index 00000000..335577c5 --- /dev/null +++ b/src/adcp/types/generated_poc/enums/metro_system.py @@ -0,0 +1,15 @@ +# generated by datamodel-codegen: +# filename: enums/metro_system.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum + + +class MetroAreaSystem(Enum): + nielsen_dma = 'nielsen_dma' + uk_itl1 = 'uk_itl1' + uk_itl2 = 'uk_itl2' + eurostat_nuts2 = 'eurostat_nuts2' + custom = 'custom' diff --git a/src/adcp/types/generated_poc/enums/notification_type.py b/src/adcp/types/generated_poc/enums/notification_type.py index 5c3fd9de..97e78847 100644 --- a/src/adcp/types/generated_poc/enums/notification_type.py +++ b/src/adcp/types/generated_poc/enums/notification_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/notification_type.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,7 +8,7 @@ class NotificationType(Enum): - scheduled = "scheduled" - final = "final" - delayed = "delayed" - adjusted = "adjusted" + scheduled = 'scheduled' + final = 'final' + delayed = 'delayed' + adjusted = 'adjusted' diff --git a/src/adcp/types/generated_poc/enums/pacing.py b/src/adcp/types/generated_poc/enums/pacing.py index 768f39fd..29c5555b 100644 --- a/src/adcp/types/generated_poc/enums/pacing.py +++ b/src/adcp/types/generated_poc/enums/pacing.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/pacing.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,6 +8,6 @@ class Pacing(Enum): - even = "even" - asap = "asap" - front_loaded = "front_loaded" + even = 'even' + asap = 'asap' + front_loaded = 'front_loaded' diff --git a/src/adcp/types/generated_poc/enums/postal_system.py b/src/adcp/types/generated_poc/enums/postal_system.py new file mode 100644 index 00000000..228d1627 --- /dev/null +++ b/src/adcp/types/generated_poc/enums/postal_system.py @@ -0,0 +1,19 @@ +# generated by datamodel-codegen: +# filename: enums/postal_system.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum + + +class PostalCodeSystem(Enum): + us_zip = 'us_zip' + us_zip_plus_four = 'us_zip_plus_four' + gb_outward = 'gb_outward' + gb_full = 'gb_full' + ca_fsa = 'ca_fsa' + ca_full = 'ca_full' + de_plz = 'de_plz' + fr_code_postal = 'fr_code_postal' + au_postcode = 'au_postcode' diff --git a/src/adcp/types/generated_poc/enums/preview_output_format.py b/src/adcp/types/generated_poc/enums/preview_output_format.py index 48f96c1c..7da1da2d 100644 --- a/src/adcp/types/generated_poc/enums/preview_output_format.py +++ b/src/adcp/types/generated_poc/enums/preview_output_format.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/preview_output_format.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,5 +8,5 @@ class PreviewOutputFormat(Enum): - url = "url" - html = "html" + url = 'url' + html = 'html' diff --git a/src/adcp/types/generated_poc/enums/pricing_model.py b/src/adcp/types/generated_poc/enums/pricing_model.py index 2a166afb..1e3f1ab1 100644 --- a/src/adcp/types/generated_poc/enums/pricing_model.py +++ b/src/adcp/types/generated_poc/enums/pricing_model.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/pricing_model.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,10 +8,10 @@ class PricingModel(Enum): - cpm = "cpm" - vcpm = "vcpm" - cpc = "cpc" - cpcv = "cpcv" - cpv = "cpv" - cpp = "cpp" - flat_rate = "flat_rate" + cpm = 'cpm' + vcpm = 'vcpm' + cpc = 'cpc' + cpcv = 'cpcv' + cpv = 'cpv' + cpp = 'cpp' + flat_rate = 'flat_rate' diff --git a/src/adcp/types/generated_poc/enums/property_type.py b/src/adcp/types/generated_poc/enums/property_type.py index f37d10d8..1d6f6985 100644 --- a/src/adcp/types/generated_poc/enums/property_type.py +++ b/src/adcp/types/generated_poc/enums/property_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/property_type.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,10 +8,11 @@ class PropertyType(Enum): - website = "website" - mobile_app = "mobile_app" - ctv_app = "ctv_app" - dooh = "dooh" - podcast = "podcast" - radio = "radio" - streaming_audio = "streaming_audio" + website = 'website' + mobile_app = 'mobile_app' + ctv_app = 'ctv_app' + desktop_app = 'desktop_app' + dooh = 'dooh' + podcast = 'podcast' + radio = 'radio' + streaming_audio = 'streaming_audio' diff --git a/src/adcp/types/generated_poc/enums/publisher_identifier_types.py b/src/adcp/types/generated_poc/enums/publisher_identifier_types.py index 20278e5f..597d5983 100644 --- a/src/adcp/types/generated_poc/enums/publisher_identifier_types.py +++ b/src/adcp/types/generated_poc/enums/publisher_identifier_types.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/publisher_identifier_types.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,8 +8,8 @@ class PublisherIdentifierTypes(Enum): - tag_id = "tag_id" - duns = "duns" - lei = "lei" - seller_id = "seller_id" - gln = "gln" + tag_id = 'tag_id' + duns = 'duns' + lei = 'lei' + seller_id = 'seller_id' + gln = 'gln' diff --git a/src/adcp/types/generated_poc/enums/reporting_frequency.py b/src/adcp/types/generated_poc/enums/reporting_frequency.py index 8d57c071..5249a966 100644 --- a/src/adcp/types/generated_poc/enums/reporting_frequency.py +++ b/src/adcp/types/generated_poc/enums/reporting_frequency.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/reporting_frequency.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,6 +8,6 @@ class ReportingFrequency(Enum): - hourly = "hourly" - daily = "daily" - monthly = "monthly" + hourly = 'hourly' + daily = 'daily' + monthly = 'monthly' diff --git a/src/adcp/types/generated_poc/enums/signal_catalog_type.py b/src/adcp/types/generated_poc/enums/signal_catalog_type.py index 9664c4d3..9535e30f 100644 --- a/src/adcp/types/generated_poc/enums/signal_catalog_type.py +++ b/src/adcp/types/generated_poc/enums/signal_catalog_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/signal_catalog_type.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,6 +8,6 @@ class SignalCatalogType(Enum): - marketplace = "marketplace" - custom = "custom" - owned = "owned" + marketplace = 'marketplace' + custom = 'custom' + owned = 'owned' diff --git a/src/adcp/types/generated_poc/enums/sort_direction.py b/src/adcp/types/generated_poc/enums/sort_direction.py index 739a21b6..abd5974e 100644 --- a/src/adcp/types/generated_poc/enums/sort_direction.py +++ b/src/adcp/types/generated_poc/enums/sort_direction.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/sort_direction.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,5 +8,5 @@ class SortDirection(Enum): - asc = "asc" - desc = "desc" + asc = 'asc' + desc = 'desc' diff --git a/src/adcp/types/generated_poc/enums/standard_format_ids.py b/src/adcp/types/generated_poc/enums/standard_format_ids.py deleted file mode 100644 index 96b4bc8c..00000000 --- a/src/adcp/types/generated_poc/enums/standard_format_ids.py +++ /dev/null @@ -1,45 +0,0 @@ -# generated by datamodel-codegen: -# filename: enums/standard_format_ids.json -# timestamp: 2025-11-29T12:00:45+00:00 - -from __future__ import annotations - -from enum import Enum - - -class StandardFormatIds(Enum): - display_300x250 = "display_300x250" - display_728x90 = "display_728x90" - display_320x50 = "display_320x50" - display_160x600 = "display_160x600" - display_970x250 = "display_970x250" - display_336x280 = "display_336x280" - display_expandable_300x250 = "display_expandable_300x250" - display_expandable_728x90 = "display_expandable_728x90" - display_interstitial_320x480 = "display_interstitial_320x480" - display_interstitial_desktop = "display_interstitial_desktop" - display_dynamic_300x250 = "display_dynamic_300x250" - display_responsive = "display_responsive" - native_in_feed = "native_in_feed" - native_content_recommendation = "native_content_recommendation" - native_product = "native_product" - video_skippable_15s = "video_skippable_15s" - video_skippable_30s = "video_skippable_30s" - video_non_skippable_15s = "video_non_skippable_15s" - video_non_skippable_30s = "video_non_skippable_30s" - video_outstream_autoplay = "video_outstream_autoplay" - video_vertical_story = "video_vertical_story" - video_rewarded_30s = "video_rewarded_30s" - video_pause_ad = "video_pause_ad" - video_ctv_non_skippable_30s = "video_ctv_non_skippable_30s" - audio_standard_15s = "audio_standard_15s" - audio_standard_30s = "audio_standard_30s" - audio_podcast_host_read = "audio_podcast_host_read" - audio_programmatic = "audio_programmatic" - universal_carousel = "universal_carousel" - universal_canvas = "universal_canvas" - universal_takeover = "universal_takeover" - universal_gallery = "universal_gallery" - universal_reveal = "universal_reveal" - dooh_landscape_static = "dooh_landscape_static" - dooh_portrait_video = "dooh_portrait_video" diff --git a/src/adcp/types/generated_poc/enums/task_status.py b/src/adcp/types/generated_poc/enums/task_status.py index 24ef178d..71f9bb0e 100644 --- a/src/adcp/types/generated_poc/enums/task_status.py +++ b/src/adcp/types/generated_poc/enums/task_status.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/task_status.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,12 +8,12 @@ class TaskStatus(Enum): - submitted = "submitted" - working = "working" - input_required = "input-required" - completed = "completed" - canceled = "canceled" - failed = "failed" - rejected = "rejected" - auth_required = "auth-required" - unknown = "unknown" + submitted = 'submitted' + working = 'working' + input_required = 'input-required' + completed = 'completed' + canceled = 'canceled' + failed = 'failed' + rejected = 'rejected' + auth_required = 'auth-required' + unknown = 'unknown' diff --git a/src/adcp/types/generated_poc/enums/task_type.py b/src/adcp/types/generated_poc/enums/task_type.py index ccaa586c..64b40043 100644 --- a/src/adcp/types/generated_poc/enums/task_type.py +++ b/src/adcp/types/generated_poc/enums/task_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/task_type.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,14 +8,14 @@ class TaskType(Enum): - create_media_buy = "create_media_buy" - update_media_buy = "update_media_buy" - sync_creatives = "sync_creatives" - activate_signal = "activate_signal" - get_signals = "get_signals" - list_property_features = "list_property_features" - create_property_list = "create_property_list" - update_property_list = "update_property_list" - get_property_list = "get_property_list" - list_property_lists = "list_property_lists" - delete_property_list = "delete_property_list" + create_media_buy = 'create_media_buy' + update_media_buy = 'update_media_buy' + sync_creatives = 'sync_creatives' + activate_signal = 'activate_signal' + get_signals = 'get_signals' + list_property_features = 'list_property_features' + create_property_list = 'create_property_list' + update_property_list = 'update_property_list' + get_property_list = 'get_property_list' + list_property_lists = 'list_property_lists' + delete_property_list = 'delete_property_list' diff --git a/src/adcp/types/generated_poc/enums/update_frequency.py b/src/adcp/types/generated_poc/enums/update_frequency.py index bb34789c..4d5d078e 100644 --- a/src/adcp/types/generated_poc/enums/update_frequency.py +++ b/src/adcp/types/generated_poc/enums/update_frequency.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/update_frequency.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,7 +8,7 @@ class UpdateFrequency(Enum): - realtime = "realtime" - hourly = "hourly" - daily = "daily" - weekly = "weekly" + realtime = 'realtime' + hourly = 'hourly' + daily = 'daily' + weekly = 'weekly' diff --git a/src/adcp/types/generated_poc/enums/url_asset_type.py b/src/adcp/types/generated_poc/enums/url_asset_type.py index 6f71b06d..3fb17a5d 100644 --- a/src/adcp/types/generated_poc/enums/url_asset_type.py +++ b/src/adcp/types/generated_poc/enums/url_asset_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/url_asset_type.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,6 +8,6 @@ class UrlAssetType(Enum): - clickthrough = "clickthrough" - tracker_pixel = "tracker_pixel" - tracker_script = "tracker_script" + clickthrough = 'clickthrough' + tracker_pixel = 'tracker_pixel' + tracker_script = 'tracker_script' diff --git a/src/adcp/types/generated_poc/enums/validation_mode.py b/src/adcp/types/generated_poc/enums/validation_mode.py index f2f5acae..47c06e5a 100644 --- a/src/adcp/types/generated_poc/enums/validation_mode.py +++ b/src/adcp/types/generated_poc/enums/validation_mode.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/validation_mode.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,5 +8,5 @@ class ValidationMode(Enum): - strict = "strict" - lenient = "lenient" + strict = 'strict' + lenient = 'lenient' diff --git a/src/adcp/types/generated_poc/enums/vast_tracking_event.py b/src/adcp/types/generated_poc/enums/vast_tracking_event.py index 9ac14497..ad8f8f2a 100644 --- a/src/adcp/types/generated_poc/enums/vast_tracking_event.py +++ b/src/adcp/types/generated_poc/enums/vast_tracking_event.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/vast_tracking_event.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,19 +8,19 @@ class VastTrackingEvent(Enum): - start = "start" - firstQuartile = "firstQuartile" - midpoint = "midpoint" - thirdQuartile = "thirdQuartile" - complete = "complete" - impression = "impression" - click = "click" - pause = "pause" - resume = "resume" - skip = "skip" - mute = "mute" - unmute = "unmute" - fullscreen = "fullscreen" - exitFullscreen = "exitFullscreen" - playerExpand = "playerExpand" - playerCollapse = "playerCollapse" + start = 'start' + firstQuartile = 'firstQuartile' + midpoint = 'midpoint' + thirdQuartile = 'thirdQuartile' + complete = 'complete' + impression = 'impression' + click = 'click' + pause = 'pause' + resume = 'resume' + skip = 'skip' + mute = 'mute' + unmute = 'unmute' + fullscreen = 'fullscreen' + exitFullscreen = 'exitFullscreen' + playerExpand = 'playerExpand' + playerCollapse = 'playerCollapse' diff --git a/src/adcp/types/generated_poc/enums/vast_version.py b/src/adcp/types/generated_poc/enums/vast_version.py index e88efe70..3d6adb4f 100644 --- a/src/adcp/types/generated_poc/enums/vast_version.py +++ b/src/adcp/types/generated_poc/enums/vast_version.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/vast_version.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,8 +8,8 @@ class VastVersion(Enum): - field_2_0 = "2.0" - field_3_0 = "3.0" - field_4_0 = "4.0" - field_4_1 = "4.1" - field_4_2 = "4.2" + field_2_0 = '2.0' + field_3_0 = '3.0' + field_4_0 = '4.0' + field_4_1 = '4.1' + field_4_2 = '4.2' diff --git a/src/adcp/types/generated_poc/enums/webhook_response_type.py b/src/adcp/types/generated_poc/enums/webhook_response_type.py index 47d9e44c..4c4080ba 100644 --- a/src/adcp/types/generated_poc/enums/webhook_response_type.py +++ b/src/adcp/types/generated_poc/enums/webhook_response_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/webhook_response_type.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,7 +8,7 @@ class WebhookResponseType(Enum): - html = "html" - json = "json" - xml = "xml" - javascript = "javascript" + html = 'html' + json = 'json' + xml = 'xml' + javascript = 'javascript' diff --git a/src/adcp/types/generated_poc/enums/webhook_security_method.py b/src/adcp/types/generated_poc/enums/webhook_security_method.py index 1b13676a..71cf8bc3 100644 --- a/src/adcp/types/generated_poc/enums/webhook_security_method.py +++ b/src/adcp/types/generated_poc/enums/webhook_security_method.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/webhook_security_method.json -# timestamp: 2025-11-29T12:00:45+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -8,6 +8,6 @@ class WebhookSecurityMethod(Enum): - hmac_sha256 = "hmac_sha256" - api_key = "api_key" - none = "none" + hmac_sha256 = 'hmac_sha256' + api_key = 'api_key' + none = 'none' diff --git a/src/adcp/types/generated_poc/extensions/extension_meta.py b/src/adcp/types/generated_poc/extensions/extension_meta.py index 7015338b..d11d0708 100644 --- a/src/adcp/types/generated_poc/extensions/extension_meta.py +++ b/src/adcp/types/generated_poc/extensions/extension_meta.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: extensions/extension_meta.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,39 +12,39 @@ class AdcpExtensionFileSchema(AdCPBaseModel): field_schema: Annotated[ - Literal["http://json-schema.org/draft-07/schema#"], Field(alias="$schema") + Literal['http://json-schema.org/draft-07/schema#'], Field(alias='$schema') ] additionalProperties: Annotated[ Any | None, - Field(description="Whether additional properties are allowed in the extension data"), + Field(description='Whether additional properties are allowed in the extension data'), ] = None - description: Annotated[str, Field(description="Description of what this extension provides")] + description: Annotated[str, Field(description='Description of what this extension provides')] docs_url: Annotated[ - AnyUrl | None, Field(description="URL to documentation for implementors of this extension") + AnyUrl | None, Field(description='URL to documentation for implementors of this extension') ] = None properties: Annotated[ dict[str, Any], - Field(description="Schema properties defining the structure of ext.{namespace} data"), + Field(description='Schema properties defining the structure of ext.{namespace} data'), ] required: Annotated[ - list[str] | None, Field(description="Required properties within the extension data") + list[str] | None, Field(description='Required properties within the extension data') ] = None - title: Annotated[str, Field(description="Human-readable title for the extension")] + title: Annotated[str, Field(description='Human-readable title for the extension')] type: Annotated[ - Literal["object"], - Field(description="Extensions must be objects (data within ext.{namespace})"), + Literal['object'], + Field(description='Extensions must be objects (data within ext.{namespace})'), ] valid_from: Annotated[ str, Field( description="Minimum AdCP version this extension is compatible with (e.g., '2.5'). Extension will be included in all versioned schema builds >= this version.", - pattern="^\\d+\\.\\d+$", + pattern='^\\d+\\.\\d+$', ), ] valid_until: Annotated[ str | None, Field( description="Last AdCP version this extension is compatible with (e.g., '3.0'). Omit if extension is still valid for current and future versions.", - pattern="^\\d+\\.\\d+$", + pattern='^\\d+\\.\\d+$', ), ] = None diff --git a/src/adcp/types/generated_poc/media_buy/build_creative_request.py b/src/adcp/types/generated_poc/media_buy/build_creative_request.py index 1d9d2b9d..0c36d124 100644 --- a/src/adcp/types/generated_poc/media_buy/build_creative_request.py +++ b/src/adcp/types/generated_poc/media_buy/build_creative_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/build_creative_request.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,25 +17,25 @@ class BuildCreativeRequest(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None creative_manifest: Annotated[ creative_manifest_1.CreativeManifest | None, Field( - description="Creative manifest to transform or generate from. For pure generation, this should include the target format_id and any required input assets (e.g., promoted_offerings for generative formats). For transformation (e.g., resizing, reformatting), this is the complete creative to adapt." + description='Creative manifest to transform or generate from. For pure generation, this should include the target format_id and any required input assets (e.g., promoted_offerings for generative formats). For transformation (e.g., resizing, reformatting), this is the complete creative to adapt.' ), ] = None ext: ext_1.ExtensionObject | None = None message: Annotated[ str | None, Field( - description="Natural language instructions for the transformation or generation. For pure generation, this is the creative brief. For transformation, this provides guidance on how to adapt the creative." + description='Natural language instructions for the transformation or generation. For pure generation, this is the creative brief. For transformation, this provides guidance on how to adapt the creative.' ), ] = None target_format_id: Annotated[ format_id.FormatId, Field( - description="Format ID to generate. The format definition specifies required input assets and output structure." + description='Format ID to generate. The format definition specifies required input assets and output structure.' ), ] diff --git a/src/adcp/types/generated_poc/media_buy/build_creative_response.py b/src/adcp/types/generated_poc/media_buy/build_creative_response.py index 034c573a..8859d39f 100644 --- a/src/adcp/types/generated_poc/media_buy/build_creative_response.py +++ b/src/adcp/types/generated_poc/media_buy/build_creative_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/build_creative_response.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,13 +17,13 @@ class BuildCreativeResponse2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ list[error.Error], Field( - description="Array of errors explaining why creative generation failed", min_length=1 + description='Array of errors explaining why creative generation failed', min_length=1 ), ] ext: ext_1.ExtensionObject | None = None @@ -31,12 +31,12 @@ class BuildCreativeResponse2(AdCPBaseModel): class BuildCreativeResponse1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None creative_manifest: Annotated[ creative_manifest_1.CreativeManifest, - Field(description="The generated or transformed creative manifest"), + Field(description='The generated or transformed creative manifest'), ] ext: ext_1.ExtensionObject | None = None @@ -45,7 +45,7 @@ class BuildCreativeResponse(RootModel[BuildCreativeResponse1 | BuildCreativeResp root: Annotated[ BuildCreativeResponse1 | BuildCreativeResponse2, Field( - description="Response containing the transformed or generated creative manifest, ready for use with preview_creative or sync_creatives. Returns either the complete creative manifest OR error information, never both.", - title="Build Creative Response", + description='Response containing the transformed or generated creative manifest, ready for use with preview_creative or sync_creatives. Returns either the complete creative manifest OR error information, never both.', + title='Build Creative Response', ), ] diff --git a/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_input_required.py b/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_input_required.py index 25aa1d52..716fb894 100644 --- a/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_input_required.py +++ b/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_input_required.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/create_media_buy_async_response_input_required.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,22 +16,22 @@ class Reason(Enum): - APPROVAL_REQUIRED = "APPROVAL_REQUIRED" - BUDGET_EXCEEDS_LIMIT = "BUDGET_EXCEEDS_LIMIT" + APPROVAL_REQUIRED = 'APPROVAL_REQUIRED' + BUDGET_EXCEEDS_LIMIT = 'BUDGET_EXCEEDS_LIMIT' class CreateMediaBuyInputRequired(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ list[error.Error] | None, Field( - description="Optional validation errors or warnings for debugging purposes. Helps explain why input is required." + description='Optional validation errors or warnings for debugging purposes. Helps explain why input is required.' ), ] = None ext: ext_1.ExtensionObject | None = None reason: Annotated[ - Reason | None, Field(description="Reason code indicating why input is needed") + Reason | None, Field(description='Reason code indicating why input is needed') ] = None diff --git a/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_submitted.py b/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_submitted.py index 6088ea7e..49a7b71b 100644 --- a/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_submitted.py +++ b/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_submitted.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/create_media_buy_async_response_submitted.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -13,7 +13,7 @@ class CreateMediaBuySubmitted(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_working.py b/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_working.py index 7950a1fa..e2c0db4c 100644 --- a/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_working.py +++ b/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_working.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/create_media_buy_async_response_working.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,17 +15,17 @@ class CreateMediaBuyWorking(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None current_step: Annotated[ - str | None, Field(description="Current step or phase of the operation") + str | None, Field(description='Current step or phase of the operation') ] = None ext: ext_1.ExtensionObject | None = None percentage: Annotated[ - float | None, Field(description="Completion percentage (0-100)", ge=0.0, le=100.0) + float | None, Field(description='Completion percentage (0-100)', ge=0.0, le=100.0) ] = None - step_number: Annotated[int | None, Field(description="Current step number", ge=1)] = None + step_number: Annotated[int | None, Field(description='Current step number', ge=1)] = None total_steps: Annotated[ - int | None, Field(description="Total number of steps in the operation", ge=1) + int | None, Field(description='Total number of steps in the operation', ge=1) ] = None diff --git a/src/adcp/types/generated_poc/media_buy/create_media_buy_request.py b/src/adcp/types/generated_poc/media_buy/create_media_buy_request.py index 6a68ec83..0e60756b 100644 --- a/src/adcp/types/generated_poc/media_buy/create_media_buy_request.py +++ b/src/adcp/types/generated_poc/media_buy/create_media_buy_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/create_media_buy_request.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -13,6 +13,7 @@ from ..core import brand_manifest_ref from ..core import context as context_1 from ..core import ext as ext_1 +from ..core import reporting_webhook as reporting_webhook_1 from ..core import start_timing from ..enums import auth_scheme from . import package_request @@ -20,12 +21,12 @@ class Authentication(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) credentials: Annotated[ str, Field( - description="Credentials for authentication. For Bearer: token sent in Authorization header. For HMAC-SHA256: shared secret used to generate signature. Minimum 32 characters. Exchanged out-of-band during onboarding.", + description='Credentials for authentication. For Bearer: token sent in Authorization header. For HMAC-SHA256: shared secret used to generate signature. Minimum 32 characters. Exchanged out-of-band during onboarding.', min_length=32, ), ] @@ -39,78 +40,105 @@ class Authentication(AdCPBaseModel): ] -class ReportingFrequency(Enum): - hourly = "hourly" - daily = "daily" - monthly = "monthly" +class BatchFrequency(Enum): + hourly = 'hourly' + daily = 'daily' -class RequestedMetric(Enum): - impressions = "impressions" - spend = "spend" - clicks = "clicks" - ctr = "ctr" - video_completions = "video_completions" - completion_rate = "completion_rate" - conversions = "conversions" - viewability = "viewability" - engagement_rate = "engagement_rate" +class DeliveryMode(Enum): + realtime = 'realtime' + batched = 'batched' -class ReportingWebhook(AdCPBaseModel): +class ArtifactWebhook(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) authentication: Annotated[ Authentication, - Field(description="Authentication configuration for webhook delivery (A2A-compatible)"), + Field(description='Authentication configuration for webhook delivery (A2A-compatible)'), ] - reporting_frequency: Annotated[ - ReportingFrequency, + batch_frequency: Annotated[ + BatchFrequency | None, Field( - description="Frequency for automated reporting delivery. Must be supported by all products in the media buy." + description="For batched delivery, how often to push artifacts. Required when delivery_mode is 'batched'." + ), + ] = None + delivery_mode: Annotated[ + DeliveryMode, + Field( + description="How artifacts are delivered. 'realtime' pushes artifacts as impressions occur. 'batched' aggregates artifacts and pushes periodically (see batch_frequency)." ), ] - requested_metrics: Annotated[ - list[RequestedMetric] | None, + sampling_rate: Annotated[ + float | None, Field( - description="Optional list of metrics to include in webhook notifications. If omitted, all available metrics are included. Must be subset of product's available_metrics." + description='Fraction of impressions to include (0-1). 1.0 = all impressions, 0.1 = 10% sample. Default: 1.0', + ge=0.0, + le=1.0, ), ] = None token: Annotated[ str | None, Field( - description="Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.", + description='Optional client-provided token for webhook validation. Echoed back in webhook payload to validate request authenticity.', min_length=16, ), ] = None - url: Annotated[AnyUrl, Field(description="Webhook endpoint URL for reporting notifications")] + url: Annotated[AnyUrl, Field(description='Webhook endpoint URL for artifact delivery')] + + +class TotalBudget(AdCPBaseModel): + model_config = ConfigDict( + extra='forbid', + ) + amount: Annotated[float, Field(description='Total budget amount', ge=0.0)] + currency: Annotated[str, Field(description='ISO 4217 currency code')] class CreateMediaBuyRequest(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) + artifact_webhook: Annotated[ + ArtifactWebhook | None, + Field( + description='Optional webhook configuration for content artifact delivery. Used by governance agents to validate content adjacency. Seller pushes artifacts to this endpoint; orchestrator forwards to governance agent for validation.' + ), + ] = None brand_manifest: Annotated[ brand_manifest_ref.BrandManifestReference, Field( - description="Brand information manifest serving as the namespace and identity for this media buy. Provides brand context, assets, and product catalog. Can be provided inline or as a URL reference to a hosted manifest. Can be cached and reused across multiple requests." + description='Brand information manifest serving as the namespace and identity for this media buy. Provides brand context, assets, and product catalog. Can be provided inline or as a URL reference to a hosted manifest. Can be cached and reused across multiple requests.' ), ] buyer_ref: Annotated[str, Field(description="Buyer's reference identifier for this media buy")] context: context_1.ContextObject | None = None end_time: Annotated[ - AwareDatetime, Field(description="Campaign end date/time in ISO 8601 format") + AwareDatetime, Field(description='Campaign end date/time in ISO 8601 format') ] ext: ext_1.ExtensionObject | None = None packages: Annotated[ - list[package_request.PackageRequest], Field(description="Array of package configurations") - ] - po_number: Annotated[str | None, Field(description="Purchase order number for tracking")] = None - reporting_webhook: Annotated[ - ReportingWebhook | None, + list[package_request.PackageRequest] | None, + Field( + description="Array of package configurations. Required when not using proposal_id. When executing a proposal, this can be omitted and packages will be derived from the proposal's allocations." + ), + ] = None + po_number: Annotated[str | None, Field(description='Purchase order number for tracking')] = None + proposal_id: Annotated[ + str | None, Field( - description="Optional webhook configuration for automated reporting delivery. Combines push_notification_config structure with reporting-specific fields." + description="ID of a proposal from get_products to execute. When provided with total_budget, the publisher converts the proposal's allocation percentages into packages automatically. Alternative to providing packages array." ), ] = None + reporting_webhook: Annotated[ + reporting_webhook_1.ReportingWebhook | None, + Field(description='Optional webhook configuration for automated reporting delivery'), + ] = None start_time: start_timing.StartTiming + total_budget: Annotated[ + TotalBudget | None, + Field( + description="Total budget for the media buy when executing a proposal. The publisher applies the proposal's allocation percentages to this amount to derive package budgets." + ), + ] = None diff --git a/src/adcp/types/generated_poc/media_buy/create_media_buy_response.py b/src/adcp/types/generated_poc/media_buy/create_media_buy_response.py index b2419451..c4c431d9 100644 --- a/src/adcp/types/generated_poc/media_buy/create_media_buy_response.py +++ b/src/adcp/types/generated_poc/media_buy/create_media_buy_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/create_media_buy_response.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,24 +17,24 @@ class CreateMediaBuyResponse2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ list[error.Error], - Field(description="Array of errors explaining why the operation failed", min_length=1), + Field(description='Array of errors explaining why the operation failed', min_length=1), ] ext: ext_1.ExtensionObject | None = None class CreateMediaBuyResponse1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) buyer_ref: Annotated[str, Field(description="Buyer's reference identifier for this media buy")] context: context_1.ContextObject | None = None creative_deadline: Annotated[ - AwareDatetime | None, Field(description="ISO 8601 timestamp for creative upload deadline") + AwareDatetime | None, Field(description='ISO 8601 timestamp for creative upload deadline') ] = None ext: ext_1.ExtensionObject | None = None media_buy_id: Annotated[ @@ -42,7 +42,7 @@ class CreateMediaBuyResponse1(AdCPBaseModel): ] packages: Annotated[ list[package.Package], - Field(description="Array of created packages with complete state information"), + Field(description='Array of created packages with complete state information'), ] @@ -50,7 +50,7 @@ class CreateMediaBuyResponse(RootModel[CreateMediaBuyResponse1 | CreateMediaBuyR root: Annotated[ CreateMediaBuyResponse1 | CreateMediaBuyResponse2, Field( - description="Response payload for create_media_buy task. Returns either complete success data OR error information, never both. This enforces atomic operation semantics - the media buy is either fully created or not created at all.", - title="Create Media Buy Response", + description='Response payload for create_media_buy task. Returns either complete success data OR error information, never both. This enforces atomic operation semantics - the media buy is either fully created or not created at all.', + title='Create Media Buy Response', ), ] diff --git a/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_request.py b/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_request.py index f293aae9..1a24abe8 100644 --- a/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_request.py +++ b/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_media_buy_delivery_request.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,32 +16,32 @@ class GetMediaBuyDeliveryRequest(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) buyer_refs: Annotated[ - list[str] | None, Field(description="Array of buyer reference IDs to get delivery data for") + list[str] | None, Field(description='Array of buyer reference IDs to get delivery data for') ] = None context: context_1.ContextObject | None = None end_date: Annotated[ str | None, Field( - description="End date for reporting period (YYYY-MM-DD)", - pattern="^\\d{4}-\\d{2}-\\d{2}$", + description='End date for reporting period (YYYY-MM-DD)', + pattern='^\\d{4}-\\d{2}-\\d{2}$', ), ] = None ext: ext_1.ExtensionObject | None = None media_buy_ids: Annotated[ list[str] | None, - Field(description="Array of publisher media buy IDs to get delivery data for"), + Field(description='Array of publisher media buy IDs to get delivery data for'), ] = None start_date: Annotated[ str | None, Field( - description="Start date for reporting period (YYYY-MM-DD)", - pattern="^\\d{4}-\\d{2}-\\d{2}$", + description='Start date for reporting period (YYYY-MM-DD)', + pattern='^\\d{4}-\\d{2}-\\d{2}$', ), ] = None status_filter: Annotated[ media_buy_status.MediaBuyStatus | list[media_buy_status.MediaBuyStatus] | None, - Field(description="Filter by status. Can be a single status or array of statuses"), + Field(description='Filter by status. Can be a single status or array of statuses'), ] = None diff --git a/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_response.py b/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_response.py index b4e662b6..96ce20e3 100644 --- a/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_response.py +++ b/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_media_buy_delivery_response.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -19,49 +19,49 @@ class AggregatedTotals(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) clicks: Annotated[ float | None, - Field(description="Total clicks across all media buys (if applicable)", ge=0.0), + Field(description='Total clicks across all media buys (if applicable)', ge=0.0), ] = None impressions: Annotated[ - float, Field(description="Total impressions delivered across all media buys", ge=0.0) + float, Field(description='Total impressions delivered across all media buys', ge=0.0) ] media_buy_count: Annotated[ - int, Field(description="Number of media buys included in the response", ge=0) + int, Field(description='Number of media buys included in the response', ge=0) ] - spend: Annotated[float, Field(description="Total amount spent across all media buys", ge=0.0)] + spend: Annotated[float, Field(description='Total amount spent across all media buys', ge=0.0)] video_completions: Annotated[ float | None, - Field(description="Total video completions across all media buys (if applicable)", ge=0.0), + Field(description='Total video completions across all media buys (if applicable)', ge=0.0), ] = None class DeliveryStatus(Enum): - delivering = "delivering" - completed = "completed" - budget_exhausted = "budget_exhausted" - flight_ended = "flight_ended" - goal_met = "goal_met" + delivering = 'delivering' + completed = 'completed' + budget_exhausted = 'budget_exhausted' + flight_ended = 'flight_ended' + goal_met = 'goal_met' class DailyBreakdownItem(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - date: Annotated[str, Field(description="Date (YYYY-MM-DD)", pattern="^\\d{4}-\\d{2}-\\d{2}$")] - impressions: Annotated[float, Field(description="Daily impressions", ge=0.0)] - spend: Annotated[float, Field(description="Daily spend", ge=0.0)] + date: Annotated[str, Field(description='Date (YYYY-MM-DD)', pattern='^\\d{4}-\\d{2}-\\d{2}$')] + impressions: Annotated[float, Field(description='Daily impressions', ge=0.0)] + spend: Annotated[float, Field(description='Daily spend', ge=0.0)] class Status(Enum): - pending = "pending" - active = "active" - paused = "paused" - completed = "completed" - failed = "failed" - reporting_delayed = "reporting_delayed" + pending = 'pending' + active = 'active' + paused = 'paused' + completed = 'completed' + failed = 'failed' + reporting_delayed = 'reporting_delayed' class Totals(DeliveryMetrics): @@ -76,23 +76,23 @@ class Totals(DeliveryMetrics): class NotificationType(Enum): - scheduled = "scheduled" - final = "final" - delayed = "delayed" - adjusted = "adjusted" + scheduled = 'scheduled' + final = 'final' + delayed = 'delayed' + adjusted = 'adjusted' class ReportingPeriod(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) end: Annotated[ AwareDatetime, - Field(description="ISO 8601 end timestamp in UTC (e.g., 2024-02-05T23:59:59Z)"), + Field(description='ISO 8601 end timestamp in UTC (e.g., 2024-02-05T23:59:59Z)'), ] start: Annotated[ AwareDatetime, - Field(description="ISO 8601 start timestamp in UTC (e.g., 2024-02-05T00:00:00Z)"), + Field(description='ISO 8601 start timestamp in UTC (e.g., 2024-02-05T00:00:00Z)'), ] @@ -104,33 +104,33 @@ class ByPackageItem(DeliveryMetrics): str, Field( description="ISO 4217 currency code (e.g., USD, EUR, GBP) for this package's pricing. Indicates the currency in which the rate and spend values are denominated. Different packages can use different currencies when supported by the publisher.", - pattern="^[A-Z]{3}$", + pattern='^[A-Z]{3}$', ), ] delivery_status: Annotated[ DeliveryStatus | None, Field( - description="System-reported operational state of this package. Reflects actual delivery state independent of buyer pause control." + description='System-reported operational state of this package. Reflects actual delivery state independent of buyer pause control.' ), ] = None pacing_index: Annotated[ float | None, - Field(description="Delivery pace (1.0 = on track, <1.0 = behind, >1.0 = ahead)", ge=0.0), + Field(description='Delivery pace (1.0 = on track, <1.0 = behind, >1.0 = ahead)', ge=0.0), ] = None package_id: Annotated[str, Field(description="Publisher's package identifier")] paused: Annotated[ - bool | None, Field(description="Whether this package is currently paused by the buyer") + bool | None, Field(description='Whether this package is currently paused by the buyer') ] = None pricing_model: Annotated[ pricing_model_1.PricingModel, Field( - description="The pricing model used for this package (e.g., cpm, cpcv, cpp). Indicates how the package is billed and which metrics are most relevant for optimization." + description='The pricing model used for this package (e.g., cpm, cpcv, cpp). Indicates how the package is billed and which metrics are most relevant for optimization.' ), ] rate: Annotated[ float, Field( - description="The pricing rate for this package in the specified currency. For fixed-rate pricing, this is the agreed rate (e.g., CPM rate of 12.50 means $12.50 per 1,000 impressions). For auction-based pricing, this represents the effective rate based on actual delivery.", + description='The pricing rate for this package in the specified currency. For fixed-rate pricing, this is the agreed rate (e.g., CPM rate of 12.50 means $12.50 per 1,000 impressions). For auction-based pricing, this represents the effective rate based on actual delivery.', ge=0.0, ), ] @@ -139,36 +139,36 @@ class ByPackageItem(DeliveryMetrics): class MediaBuyDelivery(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) buyer_ref: Annotated[ str | None, Field(description="Buyer's reference identifier for this media buy") ] = None - by_package: Annotated[list[ByPackageItem], Field(description="Metrics broken down by package")] + by_package: Annotated[list[ByPackageItem], Field(description='Metrics broken down by package')] daily_breakdown: Annotated[ - list[DailyBreakdownItem] | None, Field(description="Day-by-day delivery") + list[DailyBreakdownItem] | None, Field(description='Day-by-day delivery') ] = None expected_availability: Annotated[ AwareDatetime | None, Field( - description="When delayed data is expected to be available (only present when status is reporting_delayed)" + description='When delayed data is expected to be available (only present when status is reporting_delayed)' ), ] = None is_adjusted: Annotated[ bool | None, Field( - description="Indicates this delivery contains updated data for a previously reported period. Buyer should replace previous period data with these totals." + description='Indicates this delivery contains updated data for a previously reported period. Buyer should replace previous period data with these totals.' ), ] = None media_buy_id: Annotated[str, Field(description="Publisher's media buy identifier")] pricing_model: Annotated[ pricing_model_1.PricingModel | None, - Field(description="Pricing model used for this media buy"), + Field(description='Pricing model used for this media buy'), ] = None status: Annotated[ Status, Field( - description="Current media buy status. In webhook context, reporting_delayed indicates data temporarily unavailable." + description='Current media buy status. In webhook context, reporting_delayed indicates data temporarily unavailable.' ), ] totals: Totals @@ -176,27 +176,27 @@ class MediaBuyDelivery(AdCPBaseModel): class GetMediaBuyDeliveryResponse(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) aggregated_totals: Annotated[ AggregatedTotals | None, Field( - description="Combined metrics across all returned media buys. Only included in API responses (get_media_buy_delivery), not in webhook notifications." + description='Combined metrics across all returned media buys. Only included in API responses (get_media_buy_delivery), not in webhook notifications.' ), ] = None context: context_1.ContextObject | None = None - currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] + currency: Annotated[str, Field(description='ISO 4217 currency code', pattern='^[A-Z]{3}$')] errors: Annotated[ list[error.Error] | None, Field( - description="Task-specific errors and warnings (e.g., missing delivery data, reporting platform issues)" + description='Task-specific errors and warnings (e.g., missing delivery data, reporting platform issues)' ), ] = None ext: ext_1.ExtensionObject | None = None media_buy_deliveries: Annotated[ list[MediaBuyDelivery], Field( - description="Array of delivery data for media buys. When used in webhook notifications, may contain multiple media buys aggregated by publisher. When used in get_media_buy_delivery API responses, typically contains requested media buys." + description='Array of delivery data for media buys. When used in webhook notifications, may contain multiple media buys aggregated by publisher. When used in get_media_buy_delivery API responses, typically contains requested media buys.' ), ] next_expected_at: Annotated[ @@ -208,30 +208,30 @@ class GetMediaBuyDeliveryResponse(AdCPBaseModel): notification_type: Annotated[ NotificationType | None, Field( - description="Type of webhook notification (only present in webhook deliveries): scheduled = regular periodic update, final = campaign completed, delayed = data not yet available, adjusted = resending period with updated data" + description='Type of webhook notification (only present in webhook deliveries): scheduled = regular periodic update, final = campaign completed, delayed = data not yet available, adjusted = resending period with updated data' ), ] = None partial_data: Annotated[ bool | None, Field( - description="Indicates if any media buys in this webhook have missing/delayed data (only present in webhook deliveries)" + description='Indicates if any media buys in this webhook have missing/delayed data (only present in webhook deliveries)' ), ] = None reporting_period: Annotated[ ReportingPeriod, - Field(description="Date range for the report. All periods use UTC timezone."), + Field(description='Date range for the report. All periods use UTC timezone.'), ] sequence_number: Annotated[ int | None, Field( - description="Sequential notification number (only present in webhook deliveries, starts at 1)", + description='Sequential notification number (only present in webhook deliveries, starts at 1)', ge=1, ), ] = None unavailable_count: Annotated[ int | None, Field( - description="Number of media buys with reporting_delayed or failed status (only present in webhook deliveries when partial_data is true)", + description='Number of media buys with reporting_delayed or failed status (only present in webhook deliveries when partial_data is true)', ge=0, ), ] = None diff --git a/src/adcp/types/generated_poc/media_buy/get_products_async_response_input_required.py b/src/adcp/types/generated_poc/media_buy/get_products_async_response_input_required.py index c3b45976..7a831ee8 100644 --- a/src/adcp/types/generated_poc/media_buy/get_products_async_response_input_required.py +++ b/src/adcp/types/generated_poc/media_buy/get_products_async_response_input_required.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_async_response_input_required.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,23 +16,23 @@ class Reason(Enum): - CLARIFICATION_NEEDED = "CLARIFICATION_NEEDED" - BUDGET_REQUIRED = "BUDGET_REQUIRED" + CLARIFICATION_NEEDED = 'CLARIFICATION_NEEDED' + BUDGET_REQUIRED = 'BUDGET_REQUIRED' class GetProductsInputRequired(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None partial_results: Annotated[ list[product.Product] | None, - Field(description="Partial product results that may help inform the clarification"), + Field(description='Partial product results that may help inform the clarification'), ] = None reason: Annotated[ - Reason | None, Field(description="Reason code indicating why input is needed") + Reason | None, Field(description='Reason code indicating why input is needed') ] = None suggestions: Annotated[ - list[str] | None, Field(description="Suggested values or options for the required input") + list[str] | None, Field(description='Suggested values or options for the required input') ] = None diff --git a/src/adcp/types/generated_poc/media_buy/get_products_async_response_submitted.py b/src/adcp/types/generated_poc/media_buy/get_products_async_response_submitted.py index b00a379f..1ebf1717 100644 --- a/src/adcp/types/generated_poc/media_buy/get_products_async_response_submitted.py +++ b/src/adcp/types/generated_poc/media_buy/get_products_async_response_submitted.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_async_response_submitted.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,10 +15,10 @@ class GetProductsSubmitted(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None estimated_completion: Annotated[ - AwareDatetime | None, Field(description="Estimated completion time for the search") + AwareDatetime | None, Field(description='Estimated completion time for the search') ] = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/get_products_async_response_working.py b/src/adcp/types/generated_poc/media_buy/get_products_async_response_working.py index f3d7d1eb..f437aeda 100644 --- a/src/adcp/types/generated_poc/media_buy/get_products_async_response_working.py +++ b/src/adcp/types/generated_poc/media_buy/get_products_async_response_working.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_async_response_working.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,7 +15,7 @@ class GetProductsWorking(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None current_step: Annotated[ @@ -27,9 +27,9 @@ class GetProductsWorking(AdCPBaseModel): ext: ext_1.ExtensionObject | None = None percentage: Annotated[ float | None, - Field(description="Progress percentage of the search operation", ge=0.0, le=100.0), + Field(description='Progress percentage of the search operation', ge=0.0, le=100.0), ] = None - step_number: Annotated[int | None, Field(description="Current step number (1-indexed)")] = None + step_number: Annotated[int | None, Field(description='Current step number (1-indexed)')] = None total_steps: Annotated[ - int | None, Field(description="Total number of steps in the search process") + int | None, Field(description='Total number of steps in the search process') ] = None diff --git a/src/adcp/types/generated_poc/media_buy/get_products_request.py b/src/adcp/types/generated_poc/media_buy/get_products_request.py index 7b56d5dc..ee6c92ed 100644 --- a/src/adcp/types/generated_poc/media_buy/get_products_request.py +++ b/src/adcp/types/generated_poc/media_buy/get_products_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_request.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,16 +17,19 @@ class GetProductsRequest(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) brand_manifest: Annotated[ brand_manifest_ref.BrandManifestReference | None, Field( - description="Brand information manifest providing brand context, assets, and product catalog. Can be provided inline or as a URL reference to a hosted manifest." + description='Brand information manifest providing brand context, assets, and product catalog. Can be provided inline or as a URL reference to a hosted manifest.' ), ] = None brief: Annotated[ - str | None, Field(description="Natural language description of campaign requirements") + str | None, + Field( + description="Natural language description of campaign requirements. When refining a proposal, can include instructions like 'focus more on German speakers' or 'increase mobile allocation'." + ), ] = None context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None @@ -34,6 +37,12 @@ class GetProductsRequest(AdCPBaseModel): property_list: Annotated[ property_list_ref.PropertyListReference | None, Field( - description="[AdCP 3.0] Reference to an externally managed property list. When provided, the sales agent should filter products to only those available on properties in the list." + description='[AdCP 3.0] Reference to an externally managed property list. When provided, the sales agent should filter products to only those available on properties in the list.' + ), + ] = None + proposal_id: Annotated[ + str | None, + Field( + description='Optional proposal ID to refine. When provided with a brief, the publisher will use the brief as refinement instructions for the specified proposal and return an updated version.' ), ] = None diff --git a/src/adcp/types/generated_poc/media_buy/get_products_response.py b/src/adcp/types/generated_poc/media_buy/get_products_response.py index 91c11e17..cecfd0fd 100644 --- a/src/adcp/types/generated_poc/media_buy/get_products_response.py +++ b/src/adcp/types/generated_poc/media_buy/get_products_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_response.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,23 +12,29 @@ from ..core import context as context_1 from ..core import error from ..core import ext as ext_1 -from ..core import product +from ..core import product, proposal class GetProductsResponse(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ list[error.Error] | None, - Field(description="Task-specific errors and warnings (e.g., product filtering issues)"), + Field(description='Task-specific errors and warnings (e.g., product filtering issues)'), ] = None ext: ext_1.ExtensionObject | None = None - products: Annotated[list[product.Product], Field(description="Array of matching products")] + products: Annotated[list[product.Product], Field(description='Array of matching products')] property_list_applied: Annotated[ bool | None, Field( - description="[AdCP 3.0] Indicates whether property_list filtering was applied. True if the agent filtered products based on the provided property_list. Absent or false if property_list was not provided or not supported by this agent." + description='[AdCP 3.0] Indicates whether property_list filtering was applied. True if the agent filtered products based on the provided property_list. Absent or false if property_list was not provided or not supported by this agent.' + ), + ] = None + proposals: Annotated[ + list[proposal.Proposal] | None, + Field( + description='Optional array of proposed media plans with budget allocations across products. Publishers include proposals when they can provide strategic guidance based on the brief. Proposals are actionable - buyers can refine them via subsequent get_products calls or execute them directly via create_media_buy.' ), ] = None diff --git a/src/adcp/types/generated_poc/media_buy/list_authorized_properties_request.py b/src/adcp/types/generated_poc/media_buy/list_authorized_properties_request.py index 3f97a866..a3ef271b 100644 --- a/src/adcp/types/generated_poc/media_buy/list_authorized_properties_request.py +++ b/src/adcp/types/generated_poc/media_buy/list_authorized_properties_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/list_authorized_properties_request.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -18,21 +18,21 @@ class PublisherDomain(RootModel[str]): str, Field( description="Publisher domain to filter by (e.g., 'cnn.com', 'espn.com')", - pattern="^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$", + pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$', ), ] class ListAuthorizedPropertiesRequest(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None publisher_domains: Annotated[ list[PublisherDomain] | None, Field( - description="Filter to specific publisher domains (optional). If omitted, returns all publishers this agent represents.", + description='Filter to specific publisher domains (optional). If omitted, returns all publishers this agent represents.', min_length=1, ), ] = None diff --git a/src/adcp/types/generated_poc/media_buy/list_authorized_properties_response.py b/src/adcp/types/generated_poc/media_buy/list_authorized_properties_response.py index ad30e66e..0aba99ee 100644 --- a/src/adcp/types/generated_poc/media_buy/list_authorized_properties_response.py +++ b/src/adcp/types/generated_poc/media_buy/list_authorized_properties_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/list_authorized_properties_response.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,7 +16,7 @@ class PrimaryCountry(RootModel[str]): - root: Annotated[str, Field(pattern="^[A-Z]{2}$")] + root: Annotated[str, Field(pattern='^[A-Z]{2}$')] class PublisherDomain(RootModel[str]): @@ -24,14 +24,14 @@ class PublisherDomain(RootModel[str]): str, Field( description="Domain where publisher's adagents.json is hosted (e.g., 'cnn.com')", - pattern="^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$", + pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$', ), ] class ListAuthorizedPropertiesResponse(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) advertising_policies: Annotated[ str | None, @@ -44,7 +44,7 @@ class ListAuthorizedPropertiesResponse(AdCPBaseModel): context: context_1.ContextObject | None = None errors: Annotated[ list[error.Error] | None, - Field(description="Task-specific errors and warnings (e.g., property availability issues)"), + Field(description='Task-specific errors and warnings (e.g., property availability issues)'), ] = None ext: ext_1.ExtensionObject | None = None last_updated: Annotated[ @@ -56,22 +56,22 @@ class ListAuthorizedPropertiesResponse(AdCPBaseModel): portfolio_description: Annotated[ str | None, Field( - description="Markdown-formatted description of the property portfolio, including inventory types, audience characteristics, and special features.", + description='Markdown-formatted description of the property portfolio, including inventory types, audience characteristics, and special features.', max_length=5000, min_length=1, ), ] = None primary_channels: Annotated[ - list[channels.AdvertisingChannels] | None, + list[channels.MediaChannel] | None, Field( - description="Primary advertising channels represented in this property portfolio. Helps buying agents quickly filter relevance.", + description='Primary advertising channels represented in this property portfolio. Helps buying agents quickly filter relevance.', min_length=1, ), ] = None primary_countries: Annotated[ list[PrimaryCountry] | None, Field( - description="Primary countries (ISO 3166-1 alpha-2 codes) where properties are concentrated. Helps buying agents quickly filter relevance.", + description='Primary countries (ISO 3166-1 alpha-2 codes) where properties are concentrated. Helps buying agents quickly filter relevance.', min_length=1, ), ] = None diff --git a/src/adcp/types/generated_poc/media_buy/list_creative_formats_request.py b/src/adcp/types/generated_poc/media_buy/list_creative_formats_request.py index 89eb0639..ef77ba8e 100644 --- a/src/adcp/types/generated_poc/media_buy/list_creative_formats_request.py +++ b/src/adcp/types/generated_poc/media_buy/list_creative_formats_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/list_creative_formats_request.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class ListCreativeFormatsRequest(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) asset_types: Annotated[ list[asset_content_type.AssetContentType] | None, @@ -30,45 +30,45 @@ class ListCreativeFormatsRequest(AdCPBaseModel): format_ids: Annotated[ list[format_id.FormatId] | None, Field( - description="Return only these specific format IDs (e.g., from get_products response)" + description='Return only these specific format IDs (e.g., from get_products response)' ), ] = None is_responsive: Annotated[ bool | None, Field( - description="Filter for responsive formats that adapt to container size. When true, returns formats without fixed dimensions." + description='Filter for responsive formats that adapt to container size. When true, returns formats without fixed dimensions.' ), ] = None max_height: Annotated[ int | None, Field( - description="Maximum height in pixels (inclusive). Returns formats where ANY render has height <= this value. For multi-render formats, matches if at least one render fits." + description='Maximum height in pixels (inclusive). Returns formats where ANY render has height <= this value. For multi-render formats, matches if at least one render fits.' ), ] = None max_width: Annotated[ int | None, Field( - description="Maximum width in pixels (inclusive). Returns formats where ANY render has width <= this value. For multi-render formats, matches if at least one render fits." + description='Maximum width in pixels (inclusive). Returns formats where ANY render has width <= this value. For multi-render formats, matches if at least one render fits.' ), ] = None min_height: Annotated[ int | None, Field( - description="Minimum height in pixels (inclusive). Returns formats where ANY render has height >= this value." + description='Minimum height in pixels (inclusive). Returns formats where ANY render has height >= this value.' ), ] = None min_width: Annotated[ int | None, Field( - description="Minimum width in pixels (inclusive). Returns formats where ANY render has width >= this value." + description='Minimum width in pixels (inclusive). Returns formats where ANY render has width >= this value.' ), ] = None name_search: Annotated[ - str | None, Field(description="Search for formats by name (case-insensitive partial match)") + str | None, Field(description='Search for formats by name (case-insensitive partial match)') ] = None type: Annotated[ format_category.FormatCategory | None, Field( - description="Filter by format type (technical categories with distinct requirements)" + description='Filter by format type (technical categories with distinct requirements)' ), ] = None diff --git a/src/adcp/types/generated_poc/media_buy/list_creative_formats_response.py b/src/adcp/types/generated_poc/media_buy/list_creative_formats_response.py index cc791a14..563fef59 100644 --- a/src/adcp/types/generated_poc/media_buy/list_creative_formats_response.py +++ b/src/adcp/types/generated_poc/media_buy/list_creative_formats_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/list_creative_formats_response.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -18,7 +18,7 @@ class CreativeAgent(AdCPBaseModel): agent_name: Annotated[ - str | None, Field(description="Human-readable name for the creative agent") + str | None, Field(description='Human-readable name for the creative agent') ] = None agent_url: Annotated[ AnyUrl, @@ -28,24 +28,24 @@ class CreativeAgent(AdCPBaseModel): ] capabilities: Annotated[ list[creative_agent_capability.CreativeAgentCapability] | None, - Field(description="Capabilities this creative agent provides"), + Field(description='Capabilities this creative agent provides'), ] = None class ListCreativeFormatsResponse(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None creative_agents: Annotated[ list[CreativeAgent] | None, Field( - description="Optional: Creative agents that provide additional formats. Buyers can recursively query these agents to discover more formats. No authentication required for list_creative_formats." + description='Optional: Creative agents that provide additional formats. Buyers can recursively query these agents to discover more formats. No authentication required for list_creative_formats.' ), ] = None errors: Annotated[ list[error.Error] | None, - Field(description="Task-specific errors and warnings (e.g., format availability issues)"), + Field(description='Task-specific errors and warnings (e.g., format availability issues)'), ] = None ext: ext_1.ExtensionObject | None = None formats: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/list_creatives_request.py b/src/adcp/types/generated_poc/media_buy/list_creatives_request.py index e855347b..1b7201c0 100644 --- a/src/adcp/types/generated_poc/media_buy/list_creatives_request.py +++ b/src/adcp/types/generated_poc/media_buy/list_creatives_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/list_creatives_request.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,60 +17,60 @@ class FieldModel(Enum): - creative_id = "creative_id" - name = "name" - format = "format" - status = "status" - created_date = "created_date" - updated_date = "updated_date" - tags = "tags" - assignments = "assignments" - performance = "performance" - sub_assets = "sub_assets" + creative_id = 'creative_id' + name = 'name' + format_ = 'format' + status = 'status' + created_date = 'created_date' + updated_date = 'updated_date' + tags = 'tags' + assignments = 'assignments' + performance = 'performance' + sub_assets = 'sub_assets' class Pagination(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) limit: Annotated[ - int | None, Field(description="Maximum number of creatives to return", ge=1, le=100) + int | None, Field(description='Maximum number of creatives to return', ge=1, le=100) ] = 50 - offset: Annotated[int | None, Field(description="Number of creatives to skip", ge=0)] = 0 + offset: Annotated[int | None, Field(description='Number of creatives to skip', ge=0)] = 0 class Sort(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) direction: Annotated[ - sort_direction.SortDirection | None, Field(description="Sort direction") + sort_direction.SortDirection | None, Field(description='Sort direction') ] = sort_direction.SortDirection.desc field: Annotated[ - creative_sort_field.CreativeSortField | None, Field(description="Field to sort by") + creative_sort_field.CreativeSortField | None, Field(description='Field to sort by') ] = creative_sort_field.CreativeSortField.created_date class ListCreativesRequest(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None fields: Annotated[ list[FieldModel] | None, - Field(description="Specific fields to include in response (omit for all fields)"), + Field(description='Specific fields to include in response (omit for all fields)'), ] = None filters: creative_filters.CreativeFilters | None = None include_assignments: Annotated[ - bool | None, Field(description="Include package assignment information in response") + bool | None, Field(description='Include package assignment information in response') ] = True include_performance: Annotated[ - bool | None, Field(description="Include aggregated performance metrics in response") + bool | None, Field(description='Include aggregated performance metrics in response') ] = False include_sub_assets: Annotated[ bool | None, - Field(description="Include sub-assets (for carousel/native formats) in response"), + Field(description='Include sub-assets (for carousel/native formats) in response'), ] = False - pagination: Annotated[Pagination | None, Field(description="Pagination parameters")] = None - sort: Annotated[Sort | None, Field(description="Sorting parameters")] = None + pagination: Annotated[Pagination | None, Field(description='Pagination parameters')] = None + sort: Annotated[Sort | None, Field(description='Sorting parameters')] = None diff --git a/src/adcp/types/generated_poc/media_buy/list_creatives_response.py b/src/adcp/types/generated_poc/media_buy/list_creatives_response.py index 50b713dc..9d30d751 100644 --- a/src/adcp/types/generated_poc/media_buy/list_creatives_response.py +++ b/src/adcp/types/generated_poc/media_buy/list_creatives_response.py @@ -1,10 +1,9 @@ # generated by datamodel-codegen: # filename: media_buy/list_creatives_response.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations -from enum import Enum from typing import Annotated from adcp.types.base import AdCPBaseModel @@ -29,84 +28,82 @@ from ..enums import creative_status, sort_direction -class Status(Enum): - active = "active" - paused = "paused" - ended = "ended" - - class AssignedPackage(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - assigned_date: Annotated[AwareDatetime, Field(description="When this assignment was created")] - package_id: Annotated[str, Field(description="Package identifier")] - package_name: Annotated[str | None, Field(description="Human-readable package name")] = None - status: Annotated[Status, Field(description="Status of this specific assignment")] + assigned_date: Annotated[AwareDatetime, Field(description='When this assignment was created')] + buyer_ref: Annotated[ + str | None, Field(description="Buyer's reference identifier for this package") + ] = None + package_id: Annotated[str, Field(description='Package identifier')] class Assignments(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) assigned_packages: Annotated[ list[AssignedPackage] | None, - Field(description="List of packages this creative is assigned to"), + Field(description='List of packages this creative is assigned to'), ] = None assignment_count: Annotated[ - int, Field(description="Total number of active package assignments", ge=0) + int, Field(description='Total number of active package assignments', ge=0) ] class Performance(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) clicks: Annotated[ - int | None, Field(description="Total clicks across all assignments", ge=0) + int | None, Field(description='Total clicks across all assignments', ge=0) ] = None conversion_rate: Annotated[ - float | None, Field(description="Conversion rate across all assignments", ge=0.0, le=1.0) + float | None, Field(description='Conversion rate across all assignments', ge=0.0, le=1.0) ] = None ctr: Annotated[ - float | None, Field(description="Click-through rate (clicks/impressions)", ge=0.0, le=1.0) + float | None, Field(description='Click-through rate (clicks/impressions)', ge=0.0, le=1.0) ] = None impressions: Annotated[ - int | None, Field(description="Total impressions across all assignments", ge=0) + int | None, Field(description='Total impressions across all assignments', ge=0) ] = None last_updated: Annotated[ - AwareDatetime, Field(description="When performance data was last updated") + AwareDatetime, Field(description='When performance data was last updated') ] performance_score: Annotated[ - float | None, Field(description="Aggregated performance score (0-100)", ge=0.0, le=100.0) + float | None, Field(description='Aggregated performance score (0-100)', ge=0.0, le=100.0) ] = None class Pagination(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) current_page: Annotated[ - int | None, Field(description="Current page number (1-based)", ge=1) + int | None, Field(description='Current page number (1-based)', ge=1) ] = None - has_more: Annotated[bool, Field(description="Whether more results are available")] - limit: Annotated[int, Field(description="Maximum number of results requested", ge=1)] - offset: Annotated[int, Field(description="Number of results skipped", ge=0)] + has_more: Annotated[bool, Field(description='Whether more results are available')] + limit: Annotated[int, Field(description='Maximum number of results requested', ge=1)] + offset: Annotated[int, Field(description='Number of results skipped', ge=0)] total_pages: Annotated[ - int | None, Field(description="Total number of pages available", ge=0) + int | None, Field(description='Total number of pages available', ge=0) ] = None class StatusSummary(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - approved: Annotated[int | None, Field(description="Number of approved creatives", ge=0)] = None - archived: Annotated[int | None, Field(description="Number of archived creatives", ge=0)] = None + approved: Annotated[int | None, Field(description='Number of approved creatives', ge=0)] = None + archived: Annotated[int | None, Field(description='Number of archived creatives', ge=0)] = None pending_review: Annotated[ - int | None, Field(description="Number of creatives pending review", ge=0) + int | None, Field(description='Number of creatives pending review', ge=0) + ] = None + processing: Annotated[ + int | None, Field(description='Number of creatives being processed', ge=0) ] = None - rejected: Annotated[int | None, Field(description="Number of rejected creatives", ge=0)] = None + rejected: Annotated[int | None, Field(description='Number of rejected creatives', ge=0)] = None class SortApplied(AdCPBaseModel): @@ -116,26 +113,26 @@ class SortApplied(AdCPBaseModel): class QuerySummary(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) filters_applied: Annotated[ - list[str] | None, Field(description="List of filters that were applied to the query") + list[str] | None, Field(description='List of filters that were applied to the query') ] = None returned: Annotated[ - int, Field(description="Number of creatives returned in this response", ge=0) + int, Field(description='Number of creatives returned in this response', ge=0) ] sort_applied: Annotated[ - SortApplied | None, Field(description="Sort order that was applied") + SortApplied | None, Field(description='Sort order that was applied') ] = None total_matching: Annotated[ int, - Field(description="Total number of creatives matching filters (across all pages)", ge=0), + Field(description='Total number of creatives matching filters (across all pages)', ge=0), ] class Creative(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) assets: Annotated[ dict[ @@ -153,60 +150,60 @@ class Creative(AdCPBaseModel): | url_asset.UrlAsset, ] | None, - Field(description="Assets for this creative, keyed by asset_role"), + Field(description='Assets for this creative, keyed by asset_role'), ] = None assignments: Annotated[ Assignments | None, - Field(description="Current package assignments (included when include_assignments=true)"), + Field(description='Current package assignments (included when include_assignments=true)'), ] = None created_date: Annotated[ - AwareDatetime, Field(description="When the creative was uploaded to the library") + AwareDatetime, Field(description='When the creative was uploaded to the library') ] - creative_id: Annotated[str, Field(description="Unique identifier for the creative")] + creative_id: Annotated[str, Field(description='Unique identifier for the creative')] format_id: Annotated[ format_id_1.FormatId, - Field(description="Format identifier specifying which format this creative conforms to"), + Field(description='Format identifier specifying which format this creative conforms to'), ] - name: Annotated[str, Field(description="Human-readable creative name")] + name: Annotated[str, Field(description='Human-readable creative name')] performance: Annotated[ Performance | None, Field( - description="Aggregated performance metrics (included when include_performance=true)" + description='Aggregated performance metrics (included when include_performance=true)' ), ] = None status: Annotated[ - creative_status.CreativeStatus, Field(description="Current approval status of the creative") + creative_status.CreativeStatus, Field(description='Current approval status of the creative') ] sub_assets: Annotated[ list[sub_asset.SubAsset] | None, Field( - description="Sub-assets for multi-asset formats (included when include_sub_assets=true)" + description='Sub-assets for multi-asset formats (included when include_sub_assets=true)' ), ] = None tags: Annotated[ - list[str] | None, Field(description="User-defined tags for organization and searchability") + list[str] | None, Field(description='User-defined tags for organization and searchability') ] = None - updated_date: Annotated[AwareDatetime, Field(description="When the creative was last modified")] + updated_date: Annotated[AwareDatetime, Field(description='When the creative was last modified')] class ListCreativesResponse(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None creatives: Annotated[ - list[Creative], Field(description="Array of creative assets matching the query") + list[Creative], Field(description='Array of creative assets matching the query') ] ext: ext_1.ExtensionObject | None = None format_summary: Annotated[ - dict[str, int] | None, Field(description="Breakdown of creatives by format type") + dict[str, int] | None, Field(description='Breakdown of creatives by format type') ] = None pagination: Annotated[ - Pagination, Field(description="Pagination information for navigating results") + Pagination, Field(description='Pagination information for navigating results') ] query_summary: Annotated[ - QuerySummary, Field(description="Summary of the query that was executed") + QuerySummary, Field(description='Summary of the query that was executed') ] status_summary: Annotated[ - StatusSummary | None, Field(description="Breakdown of creatives by status") + StatusSummary | None, Field(description='Breakdown of creatives by status') ] = None diff --git a/src/adcp/types/generated_poc/media_buy/package_request.py b/src/adcp/types/generated_poc/media_buy/package_request.py index bfaf96b0..c3ee7633 100644 --- a/src/adcp/types/generated_poc/media_buy/package_request.py +++ b/src/adcp/types/generated_poc/media_buy/package_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/package_request.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -9,7 +9,7 @@ from adcp.types.base import AdCPBaseModel from pydantic import ConfigDict, Field -from ..core import creative_asset +from ..core import creative_asset, creative_assignment from ..core import ext as ext_1 from ..core import format_id, targeting from ..enums import pacing as pacing_1 @@ -17,12 +17,12 @@ class PackageRequest(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) bid_price: Annotated[ float | None, Field( - description="Bid price for auction-based CPM pricing (required if using cpm-auction-option)", + description='Bid price for auction-based CPM pricing (required if using cpm-auction-option)', ge=0.0, ), ] = None @@ -31,16 +31,16 @@ class PackageRequest(AdCPBaseModel): Field(description="Budget allocation for this package in the media buy's currency", ge=0.0), ] buyer_ref: Annotated[str, Field(description="Buyer's reference identifier for this package")] - creative_ids: Annotated[ - list[str] | None, + creative_assignments: Annotated[ + list[creative_assignment.CreativeAssignment] | None, Field( - description="Creative IDs to assign to this package at creation time (references existing library creatives)" + description='Assign existing library creatives to this package with optional weights and placement targeting' ), ] = None creatives: Annotated[ list[creative_asset.CreativeAsset] | None, Field( - description="Full creative objects to upload and assign to this package at creation time (alternative to creative_ids - creatives will be added to library). Supports both static and generative creatives.", + description='Upload new creative assets and assign to this package (creatives will be added to library). Use creative_assignments instead for existing library creatives.', max_length=100, ), ] = None @@ -48,18 +48,18 @@ class PackageRequest(AdCPBaseModel): format_ids: Annotated[ list[format_id.FormatId] | None, Field( - description="Array of format IDs that will be used for this package - must be supported by the product. If omitted, defaults to all formats supported by the product.", + description='Array of format IDs that will be used for this package - must be supported by the product. If omitted, defaults to all formats supported by the product.', min_length=1, ), ] = None impressions: Annotated[ - float | None, Field(description="Impression goal for this package", ge=0.0) + float | None, Field(description='Impression goal for this package', ge=0.0) ] = None pacing: pacing_1.Pacing | None = None paused: Annotated[ bool | None, Field( - description="Whether this package should be created in a paused state. Paused packages do not deliver impressions. Defaults to false." + description='Whether this package should be created in a paused state. Paused packages do not deliver impressions. Defaults to false.' ), ] = False pricing_option_id: Annotated[ @@ -68,5 +68,5 @@ class PackageRequest(AdCPBaseModel): description="ID of the selected pricing option from the product's pricing_options array" ), ] - product_id: Annotated[str, Field(description="Product ID for this package")] + product_id: Annotated[str, Field(description='Product ID for this package')] targeting_overlay: targeting.TargetingOverlay | None = None diff --git a/src/adcp/types/generated_poc/media_buy/package_update.py b/src/adcp/types/generated_poc/media_buy/package_update.py new file mode 100644 index 00000000..1f940090 --- /dev/null +++ b/src/adcp/types/generated_poc/media_buy/package_update.py @@ -0,0 +1,119 @@ +# generated by datamodel-codegen: +# filename: media_buy/package_update.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field, RootModel + +from ..core import creative_asset, creative_assignment +from ..core import ext as ext_1 +from ..core import targeting +from ..enums import pacing as pacing_1 + + +class PackageUpdate1(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + bid_price: Annotated[ + float | None, + Field( + description='Updated bid price for auction-based pricing options (only applies when pricing_option is auction-based)', + ge=0.0, + ), + ] = None + budget: Annotated[ + float | None, + Field( + description='Updated budget allocation for this package in the currency specified by the pricing option', + ge=0.0, + ), + ] = None + buyer_ref: Annotated[ + str | None, Field(description="Buyer's reference for the package to update") + ] = None + creative_assignments: Annotated[ + list[creative_assignment.CreativeAssignment] | None, + Field( + description='Replace creative assignments for this package with optional weights and placement targeting. Uses replacement semantics - omit to leave assignments unchanged.' + ), + ] = None + creatives: Annotated[ + list[creative_asset.CreativeAsset] | None, + Field( + description='Upload new creative assets and assign to this package (creatives will be added to library). Use creative_assignments instead for existing library creatives.', + max_length=100, + ), + ] = None + ext: ext_1.ExtensionObject | None = None + impressions: Annotated[ + float | None, Field(description='Updated impression goal for this package', ge=0.0) + ] = None + pacing: pacing_1.Pacing | None = None + package_id: Annotated[str, Field(description="Publisher's ID of package to update")] + paused: Annotated[ + bool | None, + Field(description='Pause/resume specific package (true = paused, false = active)'), + ] = None + targeting_overlay: targeting.TargetingOverlay | None = None + + +class PackageUpdate2(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + bid_price: Annotated[ + float | None, + Field( + description='Updated bid price for auction-based pricing options (only applies when pricing_option is auction-based)', + ge=0.0, + ), + ] = None + budget: Annotated[ + float | None, + Field( + description='Updated budget allocation for this package in the currency specified by the pricing option', + ge=0.0, + ), + ] = None + buyer_ref: Annotated[str, Field(description="Buyer's reference for the package to update")] + creative_assignments: Annotated[ + list[creative_assignment.CreativeAssignment] | None, + Field( + description='Replace creative assignments for this package with optional weights and placement targeting. Uses replacement semantics - omit to leave assignments unchanged.' + ), + ] = None + creatives: Annotated[ + list[creative_asset.CreativeAsset] | None, + Field( + description='Upload new creative assets and assign to this package (creatives will be added to library). Use creative_assignments instead for existing library creatives.', + max_length=100, + ), + ] = None + ext: ext_1.ExtensionObject | None = None + impressions: Annotated[ + float | None, Field(description='Updated impression goal for this package', ge=0.0) + ] = None + pacing: pacing_1.Pacing | None = None + package_id: Annotated[str | None, Field(description="Publisher's ID of package to update")] = ( + None + ) + paused: Annotated[ + bool | None, + Field(description='Pause/resume specific package (true = paused, false = active)'), + ] = None + targeting_overlay: targeting.TargetingOverlay | None = None + + +class PackageUpdate(RootModel[PackageUpdate1 | PackageUpdate2]): + root: Annotated[ + PackageUpdate1 | PackageUpdate2, + Field( + description='Package update configuration for update_media_buy. Identifies package by package_id or buyer_ref and specifies fields to modify. Fields not present are left unchanged. Note: product_id, format_ids, and pricing_option_id cannot be changed after creation.', + title='Package Update', + ), + ] diff --git a/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_request.py b/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_request.py index 712629b4..5346c2fd 100644 --- a/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_request.py +++ b/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/provide_performance_feedback_request.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,19 +17,19 @@ class MeasurementPeriod(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) end: Annotated[ - AwareDatetime, Field(description="ISO 8601 end timestamp for measurement period") + AwareDatetime, Field(description='ISO 8601 end timestamp for measurement period') ] start: Annotated[ - AwareDatetime, Field(description="ISO 8601 start timestamp for measurement period") + AwareDatetime, Field(description='ISO 8601 start timestamp for measurement period') ] class ProvidePerformanceFeedbackRequest1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) buyer_ref: Annotated[ str | None, Field(description="Buyer's reference for the media buy", min_length=1) @@ -38,33 +38,33 @@ class ProvidePerformanceFeedbackRequest1(AdCPBaseModel): creative_id: Annotated[ str | None, Field( - description="Specific creative asset (if feedback is creative-specific)", min_length=1 + description='Specific creative asset (if feedback is creative-specific)', min_length=1 ), ] = None ext: ext_1.ExtensionObject | None = None feedback_source: Annotated[ - feedback_source_1.FeedbackSource | None, Field(description="Source of the performance data") + feedback_source_1.FeedbackSource | None, Field(description='Source of the performance data') ] = feedback_source_1.FeedbackSource.buyer_attribution measurement_period: Annotated[ - MeasurementPeriod, Field(description="Time period for performance measurement") + MeasurementPeriod, Field(description='Time period for performance measurement') ] media_buy_id: Annotated[ str, Field(description="Publisher's media buy identifier", min_length=1) ] metric_type: Annotated[ - metric_type_1.MetricType | None, Field(description="The business metric being measured") + metric_type_1.MetricType | None, Field(description='The business metric being measured') ] = metric_type_1.MetricType.overall_performance package_id: Annotated[ str | None, Field( - description="Specific package within the media buy (if feedback is package-specific)", + description='Specific package within the media buy (if feedback is package-specific)', min_length=1, ), ] = None performance_index: Annotated[ float, Field( - description="Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected)", + description='Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected)', ge=0.0, ), ] @@ -72,7 +72,7 @@ class ProvidePerformanceFeedbackRequest1(AdCPBaseModel): class ProvidePerformanceFeedbackRequest2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) buyer_ref: Annotated[ str, Field(description="Buyer's reference for the media buy", min_length=1) @@ -81,33 +81,33 @@ class ProvidePerformanceFeedbackRequest2(AdCPBaseModel): creative_id: Annotated[ str | None, Field( - description="Specific creative asset (if feedback is creative-specific)", min_length=1 + description='Specific creative asset (if feedback is creative-specific)', min_length=1 ), ] = None ext: ext_1.ExtensionObject | None = None feedback_source: Annotated[ - feedback_source_1.FeedbackSource | None, Field(description="Source of the performance data") + feedback_source_1.FeedbackSource | None, Field(description='Source of the performance data') ] = feedback_source_1.FeedbackSource.buyer_attribution measurement_period: Annotated[ - MeasurementPeriod, Field(description="Time period for performance measurement") + MeasurementPeriod, Field(description='Time period for performance measurement') ] media_buy_id: Annotated[ str | None, Field(description="Publisher's media buy identifier", min_length=1) ] = None metric_type: Annotated[ - metric_type_1.MetricType | None, Field(description="The business metric being measured") + metric_type_1.MetricType | None, Field(description='The business metric being measured') ] = metric_type_1.MetricType.overall_performance package_id: Annotated[ str | None, Field( - description="Specific package within the media buy (if feedback is package-specific)", + description='Specific package within the media buy (if feedback is package-specific)', min_length=1, ), ] = None performance_index: Annotated[ float, Field( - description="Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected)", + description='Normalized performance score (0.0 = no value, 1.0 = expected, >1.0 = above expected)', ge=0.0, ), ] @@ -119,7 +119,7 @@ class ProvidePerformanceFeedbackRequest( root: Annotated[ ProvidePerformanceFeedbackRequest1 | ProvidePerformanceFeedbackRequest2, Field( - description="Request payload for provide_performance_feedback task", - title="Provide Performance Feedback Request", + description='Request payload for provide_performance_feedback task', + title='Provide Performance Feedback Request', ), ] diff --git a/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_response.py b/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_response.py index 750b9ad9..53a2a068 100644 --- a/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_response.py +++ b/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/provide_performance_feedback_response.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,25 +16,25 @@ class ProvidePerformanceFeedbackResponse1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None success: Annotated[ Literal[True], - Field(description="Whether the performance feedback was successfully received"), + Field(description='Whether the performance feedback was successfully received'), ] class ProvidePerformanceFeedbackResponse2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ list[error.Error], Field( - description="Array of errors explaining why feedback was rejected (e.g., invalid measurement period, missing campaign data)", + description='Array of errors explaining why feedback was rejected (e.g., invalid measurement period, missing campaign data)', min_length=1, ), ] @@ -47,7 +47,7 @@ class ProvidePerformanceFeedbackResponse( root: Annotated[ ProvidePerformanceFeedbackResponse1 | ProvidePerformanceFeedbackResponse2, Field( - description="Response payload for provide_performance_feedback task. Returns either success confirmation OR error information, never both.", - title="Provide Performance Feedback Response", + description='Response payload for provide_performance_feedback task. Returns either success confirmation OR error information, never both.', + title='Provide Performance Feedback Response', ), ] diff --git a/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_input_required.py b/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_input_required.py index e6022d68..ae1c3545 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_input_required.py +++ b/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_input_required.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_creatives_async_response_input_required.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,17 +15,17 @@ class Reason(Enum): - APPROVAL_REQUIRED = "APPROVAL_REQUIRED" - ASSET_CONFIRMATION = "ASSET_CONFIRMATION" - FORMAT_CLARIFICATION = "FORMAT_CLARIFICATION" + APPROVAL_REQUIRED = 'APPROVAL_REQUIRED' + ASSET_CONFIRMATION = 'ASSET_CONFIRMATION' + FORMAT_CLARIFICATION = 'FORMAT_CLARIFICATION' class SyncCreativesInputRequired(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None reason: Annotated[ - Reason | None, Field(description="Reason code indicating why buyer input is needed") + Reason | None, Field(description='Reason code indicating why buyer input is needed') ] = None diff --git a/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_submitted.py b/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_submitted.py index 504c9495..c2916196 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_submitted.py +++ b/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_submitted.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_creatives_async_response_submitted.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -13,7 +13,7 @@ class SyncCreativesSubmitted(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_working.py b/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_working.py index b53c2596..3f5cf4ea 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_working.py +++ b/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_working.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_creatives_async_response_working.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,23 +15,23 @@ class SyncCreativesWorking(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None creatives_processed: Annotated[ - int | None, Field(description="Number of creatives processed so far", ge=0) + int | None, Field(description='Number of creatives processed so far', ge=0) ] = None creatives_total: Annotated[ - int | None, Field(description="Total number of creatives to process", ge=0) + int | None, Field(description='Total number of creatives to process', ge=0) ] = None current_step: Annotated[ - str | None, Field(description="Current step or phase of the operation") + str | None, Field(description='Current step or phase of the operation') ] = None ext: ext_1.ExtensionObject | None = None percentage: Annotated[ - float | None, Field(description="Completion percentage (0-100)", ge=0.0, le=100.0) + float | None, Field(description='Completion percentage (0-100)', ge=0.0, le=100.0) ] = None - step_number: Annotated[int | None, Field(description="Current step number", ge=1)] = None + step_number: Annotated[int | None, Field(description='Current step number', ge=1)] = None total_steps: Annotated[ - int | None, Field(description="Total number of steps in the operation", ge=1) + int | None, Field(description='Total number of steps in the operation', ge=1) ] = None diff --git a/src/adcp/types/generated_poc/media_buy/sync_creatives_request.py b/src/adcp/types/generated_poc/media_buy/sync_creatives_request.py index a1655bb5..4a6ed4a0 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_creatives_request.py +++ b/src/adcp/types/generated_poc/media_buy/sync_creatives_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_creatives_request.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -18,41 +18,41 @@ class SyncCreativesRequest(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) assignments: Annotated[ dict[str, list[str]] | None, - Field(description="Optional bulk assignment of creatives to packages"), + Field(description='Optional bulk assignment of creatives to packages'), ] = None context: context_1.ContextObject | None = None creative_ids: Annotated[ list[str] | None, Field( - description="Optional filter to limit sync scope to specific creative IDs. When provided, only these creatives will be created/updated. Other creatives in the library are unaffected. Useful for partial updates and error recovery.", + description='Optional filter to limit sync scope to specific creative IDs. When provided, only these creatives will be created/updated. Other creatives in the library are unaffected. Useful for partial updates and error recovery.', max_length=100, ), ] = None creatives: Annotated[ list[creative_asset.CreativeAsset], - Field(description="Array of creative assets to sync (create or update)", max_length=100), + Field(description='Array of creative assets to sync (create or update)', max_length=100), ] delete_missing: Annotated[ bool | None, Field( - description="When true, creatives not included in this sync will be archived. Use with caution for full library replacement." + description='When true, creatives not included in this sync will be archived. Use with caution for full library replacement.' ), ] = False dry_run: Annotated[ bool | None, Field( - description="When true, preview changes without applying them. Returns what would be created/updated/deleted." + description='When true, preview changes without applying them. Returns what would be created/updated/deleted.' ), ] = False ext: ext_1.ExtensionObject | None = None push_notification_config: Annotated[ push_notification_config_1.PushNotificationConfig | None, Field( - description="Optional webhook configuration for async sync notifications. Publisher will send webhook when sync completes if operation takes longer than immediate response time (typically for large bulk operations or manual approval/HITL)." + description='Optional webhook configuration for async sync notifications. Publisher will send webhook when sync completes if operation takes longer than immediate response time (typically for large bulk operations or manual approval/HITL).' ), ] = None validation_mode: Annotated[ diff --git a/src/adcp/types/generated_poc/media_buy/sync_creatives_response.py b/src/adcp/types/generated_poc/media_buy/sync_creatives_response.py index fef20785..905dd55c 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_creatives_response.py +++ b/src/adcp/types/generated_poc/media_buy/sync_creatives_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_creatives_response.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,28 +17,28 @@ class Creative(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) action: Annotated[ - creative_action.CreativeAction, Field(description="Action taken for this creative") + creative_action.CreativeAction, Field(description='Action taken for this creative') ] assigned_to: Annotated[ list[str] | None, Field( - description="Package IDs this creative was successfully assigned to (only present when assignments were requested)" + description='Package IDs this creative was successfully assigned to (only present when assignments were requested)' ), ] = None assignment_errors: Annotated[ dict[str, str] | None, Field( - description="Assignment errors by package ID (only present when assignment failures occurred)" + description='Assignment errors by package ID (only present when assignment failures occurred)' ), ] = None changes: Annotated[ list[str] | None, Field(description="Field names that were modified (only present when action='updated')"), ] = None - creative_id: Annotated[str, Field(description="Creative ID from the request")] + creative_id: Annotated[str, Field(description='Creative ID from the request')] errors: Annotated[ list[str] | None, Field(description="Validation or processing errors (only present when action='failed')"), @@ -46,26 +46,26 @@ class Creative(AdCPBaseModel): expires_at: Annotated[ AwareDatetime | None, Field( - description="ISO 8601 timestamp when preview link expires (only present when preview_url exists)" + description='ISO 8601 timestamp when preview link expires (only present when preview_url exists)' ), ] = None platform_id: Annotated[ - str | None, Field(description="Platform-specific ID assigned to the creative") + str | None, Field(description='Platform-specific ID assigned to the creative') ] = None preview_url: Annotated[ AnyUrl | None, Field( - description="Preview URL for generative creatives (only present for generative formats)" + description='Preview URL for generative creatives (only present for generative formats)' ), ] = None warnings: Annotated[ - list[str] | None, Field(description="Non-fatal warnings about this creative") + list[str] | None, Field(description='Non-fatal warnings about this creative') ] = None class SyncCreativesResponse1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None creatives: Annotated[ @@ -75,20 +75,20 @@ class SyncCreativesResponse1(AdCPBaseModel): ), ] dry_run: Annotated[ - bool | None, Field(description="Whether this was a dry run (no actual changes made)") + bool | None, Field(description='Whether this was a dry run (no actual changes made)') ] = None ext: ext_1.ExtensionObject | None = None class SyncCreativesResponse2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ list[error.Error], Field( - description="Operation-level errors that prevented processing any creatives (e.g., authentication failure, service unavailable, invalid request format)", + description='Operation-level errors that prevented processing any creatives (e.g., authentication failure, service unavailable, invalid request format)', min_length=1, ), ] @@ -99,7 +99,7 @@ class SyncCreativesResponse(RootModel[SyncCreativesResponse1 | SyncCreativesResp root: Annotated[ SyncCreativesResponse1 | SyncCreativesResponse2, Field( - description="Response from creative sync operation. Returns either per-creative results (best-effort processing) OR operation-level errors (complete failure). This enforces atomic semantics at the operation level while allowing per-item failures within successful operations.", - title="Sync Creatives Response", + description='Response from creative sync operation. Returns either per-creative results (best-effort processing) OR operation-level errors (complete failure). This enforces atomic semantics at the operation level while allowing per-item failures within successful operations.', + title='Sync Creatives Response', ), ] diff --git a/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_input_required.py b/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_input_required.py index 1e395129..d0a984ee 100644 --- a/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_input_required.py +++ b/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_input_required.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/update_media_buy_async_response_input_required.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,16 +15,16 @@ class Reason(Enum): - APPROVAL_REQUIRED = "APPROVAL_REQUIRED" - CHANGE_CONFIRMATION = "CHANGE_CONFIRMATION" + APPROVAL_REQUIRED = 'APPROVAL_REQUIRED' + CHANGE_CONFIRMATION = 'CHANGE_CONFIRMATION' class UpdateMediaBuyInputRequired(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None reason: Annotated[ - Reason | None, Field(description="Reason code indicating why input is needed") + Reason | None, Field(description='Reason code indicating why input is needed') ] = None diff --git a/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_submitted.py b/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_submitted.py index b2cd67c0..e59f42ac 100644 --- a/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_submitted.py +++ b/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_submitted.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/update_media_buy_async_response_submitted.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -13,7 +13,7 @@ class UpdateMediaBuySubmitted(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None diff --git a/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_working.py b/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_working.py index 66f0d102..a55f2c57 100644 --- a/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_working.py +++ b/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_working.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/update_media_buy_async_response_working.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,17 +15,17 @@ class UpdateMediaBuyWorking(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None current_step: Annotated[ - str | None, Field(description="Current step or phase of the operation") + str | None, Field(description='Current step or phase of the operation') ] = None ext: ext_1.ExtensionObject | None = None percentage: Annotated[ - float | None, Field(description="Completion percentage (0-100)", ge=0.0, le=100.0) + float | None, Field(description='Completion percentage (0-100)', ge=0.0, le=100.0) ] = None - step_number: Annotated[int | None, Field(description="Current step number", ge=1)] = None + step_number: Annotated[int | None, Field(description='Current step number', ge=1)] = None total_steps: Annotated[ - int | None, Field(description="Total number of steps in the operation", ge=1) + int | None, Field(description='Total number of steps in the operation', ge=1) ] = None diff --git a/src/adcp/types/generated_poc/media_buy/update_media_buy_request.py b/src/adcp/types/generated_poc/media_buy/update_media_buy_request.py index f4da4f7d..6acfc6c0 100644 --- a/src/adcp/types/generated_poc/media_buy/update_media_buy_request.py +++ b/src/adcp/types/generated_poc/media_buy/update_media_buy_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/update_media_buy_request.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -10,174 +10,78 @@ from pydantic import AwareDatetime, ConfigDict, Field, RootModel from ..core import context as context_1 -from ..core import creative_asset, creative_assignment from ..core import ext as ext_1 from ..core import push_notification_config as push_notification_config_1 -from ..core import start_timing, targeting -from ..enums import pacing as pacing_1 - - -class Packages(AdCPBaseModel): - model_config = ConfigDict( - extra="allow", - ) - bid_price: Annotated[ - float | None, - Field( - description="Updated bid price for auction-based pricing options (only applies when pricing_option is auction-based)", - ge=0.0, - ), - ] = None - budget: Annotated[ - float | None, - Field( - description="Updated budget allocation for this package in the currency specified by the pricing option", - ge=0.0, - ), - ] = None - buyer_ref: Annotated[ - str | None, Field(description="Buyer's reference for the package to update") - ] = None - creative_assignments: Annotated[ - list[creative_assignment.CreativeAssignment] | None, - Field( - description="Full creative assignment objects with weights and placement targeting (alternative to creative_ids - provides granular control over weights and placement targeting). Uses replacement semantics like creative_ids." - ), - ] = None - creative_ids: Annotated[ - list[str] | None, - Field(description="Update creative assignments (references existing library creatives)"), - ] = None - creatives: Annotated[ - list[creative_asset.CreativeAsset] | None, - Field( - description="Full creative objects to upload and assign to this package (alternative to creative_ids - creatives will be added to library). Supports both static and generative creatives.", - max_length=100, - ), - ] = None - impressions: Annotated[ - float | None, Field(description="Updated impression goal for this package", ge=0.0) - ] = None - pacing: pacing_1.Pacing | None = None - package_id: Annotated[str, Field(description="Publisher's ID of package to update")] - paused: Annotated[ - bool | None, - Field(description="Pause/resume specific package (true = paused, false = active)"), - ] = None - targeting_overlay: targeting.TargetingOverlay | None = None - - -class Packages1(AdCPBaseModel): - model_config = ConfigDict( - extra="allow", - ) - bid_price: Annotated[ - float | None, - Field( - description="Updated bid price for auction-based pricing options (only applies when pricing_option is auction-based)", - ge=0.0, - ), - ] = None - budget: Annotated[ - float | None, - Field( - description="Updated budget allocation for this package in the currency specified by the pricing option", - ge=0.0, - ), - ] = None - buyer_ref: Annotated[str, Field(description="Buyer's reference for the package to update")] - creative_assignments: Annotated[ - list[creative_assignment.CreativeAssignment] | None, - Field( - description="Full creative assignment objects with weights and placement targeting (alternative to creative_ids - provides granular control over weights and placement targeting). Uses replacement semantics like creative_ids." - ), - ] = None - creative_ids: Annotated[ - list[str] | None, - Field(description="Update creative assignments (references existing library creatives)"), - ] = None - creatives: Annotated[ - list[creative_asset.CreativeAsset] | None, - Field( - description="Full creative objects to upload and assign to this package (alternative to creative_ids - creatives will be added to library). Supports both static and generative creatives.", - max_length=100, - ), - ] = None - impressions: Annotated[ - float | None, Field(description="Updated impression goal for this package", ge=0.0) - ] = None - pacing: pacing_1.Pacing | None = None - package_id: Annotated[str | None, Field(description="Publisher's ID of package to update")] = ( - None - ) - paused: Annotated[ - bool | None, - Field(description="Pause/resume specific package (true = paused, false = active)"), - ] = None - targeting_overlay: targeting.TargetingOverlay | None = None +from ..core import reporting_webhook as reporting_webhook_1 +from ..core import start_timing +from . import package_update class UpdateMediaBuyRequest1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) buyer_ref: Annotated[ str | None, Field(description="Buyer's reference for the media buy to update") ] = None context: context_1.ContextObject | None = None end_time: Annotated[ - AwareDatetime | None, Field(description="New end date/time in ISO 8601 format") + AwareDatetime | None, Field(description='New end date/time in ISO 8601 format') ] = None ext: ext_1.ExtensionObject | None = None media_buy_id: Annotated[str, Field(description="Publisher's ID of the media buy to update")] packages: Annotated[ - list[Packages | Packages1] | None, Field(description="Package-specific updates") + list[package_update.PackageUpdate] | None, Field(description='Package-specific updates') ] = None paused: Annotated[ bool | None, - Field(description="Pause/resume the entire media buy (true = paused, false = active)"), + Field(description='Pause/resume the entire media buy (true = paused, false = active)'), ] = None push_notification_config: Annotated[ push_notification_config_1.PushNotificationConfig | None, Field( - description="Optional webhook configuration for async update notifications. Publisher will send webhook when update completes if operation takes longer than immediate response time." + description='Optional webhook configuration for async update notifications. Publisher will send webhook when update completes if operation takes longer than immediate response time. This is separate from reporting_webhook which configures ongoing campaign reporting.' + ), + ] = None + reporting_webhook: Annotated[ + reporting_webhook_1.ReportingWebhook | None, + Field( + description='Optional webhook configuration for automated reporting delivery. Updates the reporting configuration for this media buy.' ), ] = None start_time: start_timing.StartTiming | None = None -class Packages2(Packages): - pass - - -class Packages3(Packages1): - pass - - class UpdateMediaBuyRequest2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) buyer_ref: Annotated[str, Field(description="Buyer's reference for the media buy to update")] context: context_1.ContextObject | None = None end_time: Annotated[ - AwareDatetime | None, Field(description="New end date/time in ISO 8601 format") + AwareDatetime | None, Field(description='New end date/time in ISO 8601 format') ] = None ext: ext_1.ExtensionObject | None = None media_buy_id: Annotated[ str | None, Field(description="Publisher's ID of the media buy to update") ] = None packages: Annotated[ - list[Packages2 | Packages3] | None, Field(description="Package-specific updates") + list[package_update.PackageUpdate] | None, Field(description='Package-specific updates') ] = None paused: Annotated[ bool | None, - Field(description="Pause/resume the entire media buy (true = paused, false = active)"), + Field(description='Pause/resume the entire media buy (true = paused, false = active)'), ] = None push_notification_config: Annotated[ push_notification_config_1.PushNotificationConfig | None, Field( - description="Optional webhook configuration for async update notifications. Publisher will send webhook when update completes if operation takes longer than immediate response time." + description='Optional webhook configuration for async update notifications. Publisher will send webhook when update completes if operation takes longer than immediate response time. This is separate from reporting_webhook which configures ongoing campaign reporting.' + ), + ] = None + reporting_webhook: Annotated[ + reporting_webhook_1.ReportingWebhook | None, + Field( + description='Optional webhook configuration for automated reporting delivery. Updates the reporting configuration for this media buy.' ), ] = None start_time: start_timing.StartTiming | None = None @@ -187,7 +91,7 @@ class UpdateMediaBuyRequest(RootModel[UpdateMediaBuyRequest1 | UpdateMediaBuyReq root: Annotated[ UpdateMediaBuyRequest1 | UpdateMediaBuyRequest2, Field( - description="Request parameters for updating campaign and package settings", - title="Update Media Buy Request", + description='Request parameters for updating campaign and package settings', + title='Update Media Buy Request', ), ] diff --git a/src/adcp/types/generated_poc/media_buy/update_media_buy_response.py b/src/adcp/types/generated_poc/media_buy/update_media_buy_response.py index 7ea1e655..ef962c3f 100644 --- a/src/adcp/types/generated_poc/media_buy/update_media_buy_response.py +++ b/src/adcp/types/generated_poc/media_buy/update_media_buy_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/update_media_buy_response.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,30 +17,30 @@ class UpdateMediaBuyResponse2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ list[error.Error], - Field(description="Array of errors explaining why the operation failed", min_length=1), + Field(description='Array of errors explaining why the operation failed', min_length=1), ] ext: ext_1.ExtensionObject | None = None class UpdateMediaBuyResponse1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) affected_packages: Annotated[ list[package.Package] | None, - Field(description="Array of packages that were modified with complete state information"), + Field(description='Array of packages that were modified with complete state information'), ] = None buyer_ref: Annotated[str, Field(description="Buyer's reference identifier for the media buy")] context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None implementation_date: Annotated[ AwareDatetime | None, - Field(description="ISO 8601 timestamp when changes take effect (null if pending approval)"), + Field(description='ISO 8601 timestamp when changes take effect (null if pending approval)'), ] = None media_buy_id: Annotated[str, Field(description="Publisher's identifier for the media buy")] @@ -49,7 +49,7 @@ class UpdateMediaBuyResponse(RootModel[UpdateMediaBuyResponse1 | UpdateMediaBuyR root: Annotated[ UpdateMediaBuyResponse1 | UpdateMediaBuyResponse2, Field( - description="Response payload for update_media_buy task. Returns either complete success data OR error information, never both. This enforces atomic operation semantics - updates are either fully applied or not applied at all.", - title="Update Media Buy Response", + description='Response payload for update_media_buy task. Returns either complete success data OR error information, never both. This enforces atomic operation semantics - updates are either fully applied or not applied at all.', + title='Update Media Buy Response', ), ] diff --git a/src/adcp/types/generated_poc/pricing_options/cpc_option.py b/src/adcp/types/generated_poc/pricing_options/cpc_option.py index 558dff11..1aa3537a 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpc_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpc_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpc_option.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,32 +12,32 @@ class CpcPricingOption(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) currency: Annotated[ str, Field( - description="ISO 4217 currency code", - examples=["USD", "EUR", "GBP", "JPY"], - pattern="^[A-Z]{3}$", + description='ISO 4217 currency code', + examples=['USD', 'EUR', 'GBP', 'JPY'], + pattern='^[A-Z]{3}$', ), ] is_fixed: Annotated[ Literal[True], - Field(description="Whether this is a fixed rate (true) or auction-based (false)"), + Field(description='Whether this is a fixed rate (true) or auction-based (false)'), ] min_spend_per_package: Annotated[ float | None, Field( - description="Minimum spend requirement per package using this pricing option, in the specified currency", + description='Minimum spend requirement per package using this pricing option, in the specified currency', ge=0.0, ), ] = None - pricing_model: Annotated[Literal["cpc"], Field(description="Cost per click")] + pricing_model: Annotated[Literal['cpc'], Field(description='Cost per click')] pricing_option_id: Annotated[ str, Field( description="Unique identifier for this pricing option within the product (e.g., 'cpc_usd_fixed')" ), ] - rate: Annotated[float, Field(description="Fixed CPC rate (cost per click)", ge=0.0)] + rate: Annotated[float, Field(description='Fixed CPC rate (cost per click)', ge=0.0)] diff --git a/src/adcp/types/generated_poc/pricing_options/cpcv_option.py b/src/adcp/types/generated_poc/pricing_options/cpcv_option.py index 6765ba50..d76f4b53 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpcv_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpcv_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpcv_option.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,29 +12,29 @@ class CpcvPricingOption(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) currency: Annotated[ str, Field( - description="ISO 4217 currency code", - examples=["USD", "EUR", "GBP", "JPY"], - pattern="^[A-Z]{3}$", + description='ISO 4217 currency code', + examples=['USD', 'EUR', 'GBP', 'JPY'], + pattern='^[A-Z]{3}$', ), ] is_fixed: Annotated[ Literal[True], - Field(description="Whether this is a fixed rate (true) or auction-based (false)"), + Field(description='Whether this is a fixed rate (true) or auction-based (false)'), ] min_spend_per_package: Annotated[ float | None, Field( - description="Minimum spend requirement per package using this pricing option, in the specified currency", + description='Minimum spend requirement per package using this pricing option, in the specified currency', ge=0.0, ), ] = None pricing_model: Annotated[ - Literal["cpcv"], Field(description="Cost per completed view (100% completion)") + Literal['cpcv'], Field(description='Cost per completed view (100% completion)') ] pricing_option_id: Annotated[ str, @@ -42,4 +42,4 @@ class CpcvPricingOption(AdCPBaseModel): description="Unique identifier for this pricing option within the product (e.g., 'cpcv_usd_guaranteed')" ), ] - rate: Annotated[float, Field(description="Fixed CPCV rate (cost per 100% completion)", ge=0.0)] + rate: Annotated[float, Field(description='Fixed CPCV rate (cost per 100% completion)', ge=0.0)] diff --git a/src/adcp/types/generated_poc/pricing_options/cpm_auction_option.py b/src/adcp/types/generated_poc/pricing_options/cpm_auction_option.py index e8de619b..46bb081a 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpm_auction_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpm_auction_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpm_auction_option.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,42 +14,42 @@ class PriceGuidance(AdCPBaseModel): floor: Annotated[ float, Field( - description="Minimum bid price - publisher will reject bids under this value", ge=0.0 + description='Minimum bid price - publisher will reject bids under this value', ge=0.0 ), ] - p25: Annotated[float | None, Field(description="25th percentile winning price", ge=0.0)] = None - p50: Annotated[float | None, Field(description="Median winning price", ge=0.0)] = None - p75: Annotated[float | None, Field(description="75th percentile winning price", ge=0.0)] = None - p90: Annotated[float | None, Field(description="90th percentile winning price", ge=0.0)] = None + p25: Annotated[float | None, Field(description='25th percentile winning price', ge=0.0)] = None + p50: Annotated[float | None, Field(description='Median winning price', ge=0.0)] = None + p75: Annotated[float | None, Field(description='75th percentile winning price', ge=0.0)] = None + p90: Annotated[float | None, Field(description='90th percentile winning price', ge=0.0)] = None class CpmAuctionPricingOption(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) currency: Annotated[ str, Field( - description="ISO 4217 currency code", - examples=["USD", "EUR", "GBP", "JPY"], - pattern="^[A-Z]{3}$", + description='ISO 4217 currency code', + examples=['USD', 'EUR', 'GBP', 'JPY'], + pattern='^[A-Z]{3}$', ), ] is_fixed: Annotated[ Literal[False], - Field(description="Whether this is a fixed rate (true) or auction-based (false)"), + Field(description='Whether this is a fixed rate (true) or auction-based (false)'), ] min_spend_per_package: Annotated[ float | None, Field( - description="Minimum spend requirement per package using this pricing option, in the specified currency", + description='Minimum spend requirement per package using this pricing option, in the specified currency', ge=0.0, ), ] = None price_guidance: Annotated[ - PriceGuidance, Field(description="Pricing guidance for auction-based CPM bidding") + PriceGuidance, Field(description='Pricing guidance for auction-based CPM bidding') ] - pricing_model: Annotated[Literal["cpm"], Field(description="Cost per 1,000 impressions")] + pricing_model: Annotated[Literal['cpm'], Field(description='Cost per 1,000 impressions')] pricing_option_id: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/pricing_options/cpm_fixed_option.py b/src/adcp/types/generated_poc/pricing_options/cpm_fixed_option.py index db5a3e1e..a11ef7ee 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpm_fixed_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpm_fixed_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpm_fixed_option.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,32 +12,32 @@ class CpmFixedRatePricingOption(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) currency: Annotated[ str, Field( - description="ISO 4217 currency code", - examples=["USD", "EUR", "GBP", "JPY"], - pattern="^[A-Z]{3}$", + description='ISO 4217 currency code', + examples=['USD', 'EUR', 'GBP', 'JPY'], + pattern='^[A-Z]{3}$', ), ] is_fixed: Annotated[ Literal[True], - Field(description="Whether this is a fixed rate (true) or auction-based (false)"), + Field(description='Whether this is a fixed rate (true) or auction-based (false)'), ] min_spend_per_package: Annotated[ float | None, Field( - description="Minimum spend requirement per package using this pricing option, in the specified currency", + description='Minimum spend requirement per package using this pricing option, in the specified currency', ge=0.0, ), ] = None - pricing_model: Annotated[Literal["cpm"], Field(description="Cost per 1,000 impressions")] + pricing_model: Annotated[Literal['cpm'], Field(description='Cost per 1,000 impressions')] pricing_option_id: Annotated[ str, Field( description="Unique identifier for this pricing option within the product (e.g., 'cpm_usd_guaranteed')" ), ] - rate: Annotated[float, Field(description="Fixed CPM rate (cost per 1,000 impressions)", ge=0.0)] + rate: Annotated[float, Field(description='Fixed CPM rate (cost per 1,000 impressions)', ge=0.0)] diff --git a/src/adcp/types/generated_poc/pricing_options/cpp_option.py b/src/adcp/types/generated_poc/pricing_options/cpp_option.py index 807cd3cc..93506f84 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpp_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpp_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpp_option.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,53 +12,53 @@ class Parameters(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) demographic: Annotated[ str, Field( - description="Target demographic in Nielsen format: P/M/W/A/C + age range. Examples: P18-49 (Persons 18-49), M25-54 (Men 25-54), W35+ (Women 35+), A18-34 (Adults 18-34), C2-11 (Children 2-11)", - pattern="^[PMWAC][0-9]{2}(-[0-9]{2}|\\+)$", + description='Target demographic in Nielsen format: P/M/W/A/C + age range. Examples: P18-49 (Persons 18-49), M25-54 (Men 25-54), W35+ (Women 35+), A18-34 (Adults 18-34), C2-11 (Children 2-11)', + pattern='^[PMWAC][0-9]{2}(-[0-9]{2}|\\+)$', ), ] min_points: Annotated[ float | None, - Field(description="Minimum GRPs/TRPs required for this pricing option", ge=0.0), + Field(description='Minimum GRPs/TRPs required for this pricing option', ge=0.0), ] = None class CppPricingOption(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) currency: Annotated[ str, Field( - description="ISO 4217 currency code", - examples=["USD", "EUR", "GBP", "JPY"], - pattern="^[A-Z]{3}$", + description='ISO 4217 currency code', + examples=['USD', 'EUR', 'GBP', 'JPY'], + pattern='^[A-Z]{3}$', ), ] is_fixed: Annotated[ Literal[True], - Field(description="Whether this is a fixed rate (true) or auction-based (false)"), + Field(description='Whether this is a fixed rate (true) or auction-based (false)'), ] min_spend_per_package: Annotated[ float | None, Field( - description="Minimum spend requirement per package using this pricing option, in the specified currency", + description='Minimum spend requirement per package using this pricing option, in the specified currency', ge=0.0, ), ] = None parameters: Annotated[ Parameters, - Field(description="CPP-specific parameters for demographic targeting and GRP requirements"), + Field(description='CPP-specific parameters for demographic targeting and GRP requirements'), ] - pricing_model: Annotated[Literal["cpp"], Field(description="Cost per Gross Rating Point")] + pricing_model: Annotated[Literal['cpp'], Field(description='Cost per Gross Rating Point')] pricing_option_id: Annotated[ str, Field( description="Unique identifier for this pricing option within the product (e.g., 'cpp_usd_p18-49')" ), ] - rate: Annotated[float, Field(description="Fixed CPP rate (cost per rating point)", ge=0.0)] + rate: Annotated[float, Field(description='Fixed CPP rate (cost per rating point)', ge=0.0)] diff --git a/src/adcp/types/generated_poc/pricing_options/cpv_option.py b/src/adcp/types/generated_poc/pricing_options/cpv_option.py index 793c22c4..189f40dd 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpv_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpv_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpv_option.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,7 +14,7 @@ class ViewThreshold(RootModel[float]): root: Annotated[ float, Field( - description="Percentage completion threshold for CPV pricing (0.0 to 1.0, e.g., 0.5 = 50% completion)", + description='Percentage completion threshold for CPV pricing (0.0 to 1.0, e.g., 0.5 = 50% completion)', ge=0.0, le=1.0, ), @@ -23,7 +23,7 @@ class ViewThreshold(RootModel[float]): class ViewThreshold1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) duration_seconds: Annotated[ int, @@ -36,42 +36,42 @@ class ViewThreshold1(AdCPBaseModel): class Parameters(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) view_threshold: ViewThreshold | ViewThreshold1 class CpvPricingOption(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) currency: Annotated[ str, Field( - description="ISO 4217 currency code", - examples=["USD", "EUR", "GBP", "JPY"], - pattern="^[A-Z]{3}$", + description='ISO 4217 currency code', + examples=['USD', 'EUR', 'GBP', 'JPY'], + pattern='^[A-Z]{3}$', ), ] is_fixed: Annotated[ Literal[True], - Field(description="Whether this is a fixed rate (true) or auction-based (false)"), + Field(description='Whether this is a fixed rate (true) or auction-based (false)'), ] min_spend_per_package: Annotated[ float | None, Field( - description="Minimum spend requirement per package using this pricing option, in the specified currency", + description='Minimum spend requirement per package using this pricing option, in the specified currency', ge=0.0, ), ] = None parameters: Annotated[ - Parameters, Field(description="CPV-specific parameters defining the view threshold") + Parameters, Field(description='CPV-specific parameters defining the view threshold') ] - pricing_model: Annotated[Literal["cpv"], Field(description="Cost per view at threshold")] + pricing_model: Annotated[Literal['cpv'], Field(description='Cost per view at threshold')] pricing_option_id: Annotated[ str, Field( description="Unique identifier for this pricing option within the product (e.g., 'cpv_usd_50pct')" ), ] - rate: Annotated[float, Field(description="Fixed CPV rate (cost per view)", ge=0.0)] + rate: Annotated[float, Field(description='Fixed CPV rate (cost per view)', ge=0.0)] diff --git a/src/adcp/types/generated_poc/pricing_options/flat_rate_option.py b/src/adcp/types/generated_poc/pricing_options/flat_rate_option.py index 762e7bc3..d6eec0cd 100644 --- a/src/adcp/types/generated_poc/pricing_options/flat_rate_option.py +++ b/src/adcp/types/generated_poc/pricing_options/flat_rate_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/flat_rate_option.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,7 +12,7 @@ class Parameters(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) daypart: Annotated[ str | None, @@ -22,28 +22,28 @@ class Parameters(AdCPBaseModel): ] = None duration_hours: Annotated[ float | None, - Field(description="Duration in hours for time-based flat rate pricing (DOOH)", ge=0.0), + Field(description='Duration in hours for time-based flat rate pricing (DOOH)', ge=0.0), ] = None estimated_impressions: Annotated[ int | None, Field( - description="Estimated impressions for this flat rate option (informational, commonly used with SOV or time-based DOOH)", + description='Estimated impressions for this flat rate option (informational, commonly used with SOV or time-based DOOH)', ge=0, ), ] = None loop_duration_seconds: Annotated[ - int | None, Field(description="Duration of ad loop rotation in seconds (DOOH)", ge=1) + int | None, Field(description='Duration of ad loop rotation in seconds (DOOH)', ge=1) ] = None min_plays_per_hour: Annotated[ int | None, Field( - description="Minimum number of times ad plays per hour (DOOH frequency guarantee)", ge=0 + description='Minimum number of times ad plays per hour (DOOH frequency guarantee)', ge=0 ), ] = None sov_percentage: Annotated[ float | None, Field( - description="Guaranteed share of voice as percentage (DOOH, 0-100)", ge=0.0, le=100.0 + description='Guaranteed share of voice as percentage (DOOH, 0-100)', ge=0.0, le=100.0 ), ] = None venue_package: Annotated[ @@ -56,33 +56,33 @@ class Parameters(AdCPBaseModel): class FlatRatePricingOption(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) currency: Annotated[ str, Field( - description="ISO 4217 currency code", - examples=["USD", "EUR", "GBP", "JPY"], - pattern="^[A-Z]{3}$", + description='ISO 4217 currency code', + examples=['USD', 'EUR', 'GBP', 'JPY'], + pattern='^[A-Z]{3}$', ), ] is_fixed: Annotated[ Literal[True], - Field(description="Whether this is a fixed rate (true) or auction-based (false)"), + Field(description='Whether this is a fixed rate (true) or auction-based (false)'), ] min_spend_per_package: Annotated[ float | None, Field( - description="Minimum spend requirement per package using this pricing option, in the specified currency", + description='Minimum spend requirement per package using this pricing option, in the specified currency', ge=0.0, ), ] = None parameters: Annotated[ Parameters | None, - Field(description="Flat rate parameters for DOOH and time-based campaigns"), + Field(description='Flat rate parameters for DOOH and time-based campaigns'), ] = None pricing_model: Annotated[ - Literal["flat_rate"], Field(description="Fixed cost regardless of delivery volume") + Literal['flat_rate'], Field(description='Fixed cost regardless of delivery volume') ] pricing_option_id: Annotated[ str, @@ -90,4 +90,4 @@ class FlatRatePricingOption(AdCPBaseModel): description="Unique identifier for this pricing option within the product (e.g., 'flat_rate_usd_24h_takeover')" ), ] - rate: Annotated[float, Field(description="Flat rate cost", ge=0.0)] + rate: Annotated[float, Field(description='Flat rate cost', ge=0.0)] diff --git a/src/adcp/types/generated_poc/pricing_options/vcpm_auction_option.py b/src/adcp/types/generated_poc/pricing_options/vcpm_auction_option.py index 6e017f1f..d2c9be3c 100644 --- a/src/adcp/types/generated_poc/pricing_options/vcpm_auction_option.py +++ b/src/adcp/types/generated_poc/pricing_options/vcpm_auction_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/vcpm_auction_option.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -11,47 +11,47 @@ class PriceGuidance(AdCPBaseModel): - floor: Annotated[float, Field(description="Minimum acceptable bid price", ge=0.0)] + floor: Annotated[float, Field(description='Minimum acceptable bid price', ge=0.0)] p25: Annotated[ - float | None, Field(description="25th percentile of recent winning bids", ge=0.0) + float | None, Field(description='25th percentile of recent winning bids', ge=0.0) ] = None - p50: Annotated[float | None, Field(description="Median of recent winning bids", ge=0.0)] = None + p50: Annotated[float | None, Field(description='Median of recent winning bids', ge=0.0)] = None p75: Annotated[ - float | None, Field(description="75th percentile of recent winning bids", ge=0.0) + float | None, Field(description='75th percentile of recent winning bids', ge=0.0) ] = None p90: Annotated[ - float | None, Field(description="90th percentile of recent winning bids", ge=0.0) + float | None, Field(description='90th percentile of recent winning bids', ge=0.0) ] = None class VcpmAuctionPricingOption(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) currency: Annotated[ str, Field( - description="ISO 4217 currency code", - examples=["USD", "EUR", "GBP", "JPY"], - pattern="^[A-Z]{3}$", + description='ISO 4217 currency code', + examples=['USD', 'EUR', 'GBP', 'JPY'], + pattern='^[A-Z]{3}$', ), ] is_fixed: Annotated[ Literal[False], - Field(description="Whether this is a fixed rate (true) or auction-based (false)"), + Field(description='Whether this is a fixed rate (true) or auction-based (false)'), ] min_spend_per_package: Annotated[ float | None, Field( - description="Minimum spend requirement per package using this pricing option, in the specified currency", + description='Minimum spend requirement per package using this pricing option, in the specified currency', ge=0.0, ), ] = None price_guidance: Annotated[ - PriceGuidance, Field(description="Statistical guidance for auction pricing") + PriceGuidance, Field(description='Statistical guidance for auction pricing') ] pricing_model: Annotated[ - Literal["vcpm"], Field(description="Cost per 1,000 viewable impressions (MRC standard)") + Literal['vcpm'], Field(description='Cost per 1,000 viewable impressions (MRC standard)') ] pricing_option_id: Annotated[ str, diff --git a/src/adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py b/src/adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py index acbaf110..420116ce 100644 --- a/src/adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py +++ b/src/adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/vcpm_fixed_option.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,29 +12,29 @@ class VcpmFixedRatePricingOption(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) currency: Annotated[ str, Field( - description="ISO 4217 currency code", - examples=["USD", "EUR", "GBP", "JPY"], - pattern="^[A-Z]{3}$", + description='ISO 4217 currency code', + examples=['USD', 'EUR', 'GBP', 'JPY'], + pattern='^[A-Z]{3}$', ), ] is_fixed: Annotated[ Literal[True], - Field(description="Whether this is a fixed rate (true) or auction-based (false)"), + Field(description='Whether this is a fixed rate (true) or auction-based (false)'), ] min_spend_per_package: Annotated[ float | None, Field( - description="Minimum spend requirement per package using this pricing option, in the specified currency", + description='Minimum spend requirement per package using this pricing option, in the specified currency', ge=0.0, ), ] = None pricing_model: Annotated[ - Literal["vcpm"], Field(description="Cost per 1,000 viewable impressions (MRC standard)") + Literal['vcpm'], Field(description='Cost per 1,000 viewable impressions (MRC standard)') ] pricing_option_id: Annotated[ str, @@ -43,5 +43,5 @@ class VcpmFixedRatePricingOption(AdCPBaseModel): ), ] rate: Annotated[ - float, Field(description="Fixed vCPM rate (cost per 1,000 viewable impressions)", ge=0.0) + float, Field(description='Fixed vCPM rate (cost per 1,000 viewable impressions)', ge=0.0) ] diff --git a/src/adcp/types/generated_poc/property/base_property_source.py b/src/adcp/types/generated_poc/property/base_property_source.py index aadc0111..84f31aeb 100644 --- a/src/adcp/types/generated_poc/property/base_property_source.py +++ b/src/adcp/types/generated_poc/property/base_property_source.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/base_property_source.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,18 +14,18 @@ class BasePropertySource1(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) publisher_domain: Annotated[ str, Field( description="Domain where publisher's adagents.json is hosted (e.g., 'raptive.com')", - pattern="^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$", + pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$', ), ] selection_type: Annotated[ - Literal["publisher_tags"], - Field(description="Discriminator indicating selection by property tags within a publisher"), + Literal['publisher_tags'], + Field(description='Discriminator indicating selection by property tags within a publisher'), ] tags: Annotated[ list[property_tag.PropertyTag], @@ -38,7 +38,7 @@ class BasePropertySource1(AdCPBaseModel): class BasePropertySource2(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) property_ids: Annotated[ list[property_id.PropertyId], @@ -48,28 +48,28 @@ class BasePropertySource2(AdCPBaseModel): str, Field( description="Domain where publisher's adagents.json is hosted (e.g., 'raptive.com')", - pattern="^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$", + pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$', ), ] selection_type: Annotated[ - Literal["publisher_ids"], + Literal['publisher_ids'], Field( - description="Discriminator indicating selection by specific property IDs within a publisher" + description='Discriminator indicating selection by specific property IDs within a publisher' ), ] class BasePropertySource3(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) identifiers: Annotated[ list[identifier.Identifier], - Field(description="Direct property identifiers (domains, app IDs, etc.)", min_length=1), + Field(description='Direct property identifiers (domains, app IDs, etc.)', min_length=1), ] selection_type: Annotated[ - Literal["identifiers"], - Field(description="Discriminator indicating selection by direct identifiers"), + Literal['identifiers'], + Field(description='Discriminator indicating selection by direct identifiers'), ] @@ -79,8 +79,8 @@ class BasePropertySource( root: Annotated[ BasePropertySource1 | BasePropertySource2 | BasePropertySource3, Field( - description="A source of properties for a property list. Supports three selection patterns: publisher with tags, publisher with property IDs, or direct identifiers.", - discriminator="selection_type", - title="Base Property Source", + description='A source of properties for a property list. Supports three selection patterns: publisher with tags, publisher with property IDs, or direct identifiers.', + discriminator='selection_type', + title='Base Property Source', ), ] diff --git a/src/adcp/types/generated_poc/property/create_property_list_request.py b/src/adcp/types/generated_poc/property/create_property_list_request.py index 820e53d7..bcbd8453 100644 --- a/src/adcp/types/generated_poc/property/create_property_list_request.py +++ b/src/adcp/types/generated_poc/property/create_property_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/create_property_list_request.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class CreatePropertyListRequest(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) base_properties: Annotated[ list[base_property_source.BasePropertySource] | None, @@ -28,7 +28,7 @@ class CreatePropertyListRequest(AdCPBaseModel): brand_manifest: Annotated[ brand_manifest_1.BrandManifest | None, Field( - description="Brand identity and requirements. When provided, the agent automatically applies appropriate rules based on brand characteristics (industry, target_audience, etc.)." + description='Brand identity and requirements. When provided, the agent automatically applies appropriate rules based on brand characteristics (industry, target_audience, etc.).' ), ] = None context: context_1.ContextObject | None = None @@ -38,6 +38,6 @@ class CreatePropertyListRequest(AdCPBaseModel): ext: ext_1.ExtensionObject | None = None filters: Annotated[ property_list_filters.PropertyListFilters | None, - Field(description="Dynamic filters to apply when resolving the list"), + Field(description='Dynamic filters to apply when resolving the list'), ] = None - name: Annotated[str, Field(description="Human-readable name for the list")] + name: Annotated[str, Field(description='Human-readable name for the list')] diff --git a/src/adcp/types/generated_poc/property/create_property_list_response.py b/src/adcp/types/generated_poc/property/create_property_list_response.py index c8927596..4b9ea7fe 100644 --- a/src/adcp/types/generated_poc/property/create_property_list_response.py +++ b/src/adcp/types/generated_poc/property/create_property_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/create_property_list_response.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,13 +15,13 @@ class CreatePropertyListResponse(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) auth_token: Annotated[ str, Field( - description="Token that can be shared with sellers to authorize fetching this list. Store this - it is only returned at creation time." + description='Token that can be shared with sellers to authorize fetching this list. Store this - it is only returned at creation time.' ), ] ext: ext_1.ExtensionObject | None = None - list: Annotated[property_list.PropertyList, Field(description="The created property list")] + list: Annotated[property_list.PropertyList, Field(description='The created property list')] diff --git a/src/adcp/types/generated_poc/property/delete_property_list_request.py b/src/adcp/types/generated_poc/property/delete_property_list_request.py index 4729a744..957421e3 100644 --- a/src/adcp/types/generated_poc/property/delete_property_list_request.py +++ b/src/adcp/types/generated_poc/property/delete_property_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/delete_property_list_request.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,8 +15,8 @@ class DeletePropertyListRequest(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) context: context_1.ContextObject | None = None ext: ext_1.ExtensionObject | None = None - list_id: Annotated[str, Field(description="ID of the property list to delete")] + list_id: Annotated[str, Field(description='ID of the property list to delete')] diff --git a/src/adcp/types/generated_poc/property/delete_property_list_response.py b/src/adcp/types/generated_poc/property/delete_property_list_response.py index 3def64b6..50c09857 100644 --- a/src/adcp/types/generated_poc/property/delete_property_list_response.py +++ b/src/adcp/types/generated_poc/property/delete_property_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/delete_property_list_response.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,8 +14,8 @@ class DeletePropertyListResponse(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) - deleted: Annotated[bool, Field(description="Whether the list was successfully deleted")] + deleted: Annotated[bool, Field(description='Whether the list was successfully deleted')] ext: ext_1.ExtensionObject | None = None - list_id: Annotated[str, Field(description="ID of the deleted list")] + list_id: Annotated[str, Field(description='ID of the deleted list')] diff --git a/src/adcp/types/generated_poc/property/feature_requirement.py b/src/adcp/types/generated_poc/property/feature_requirement.py index 1ea5e6f7..5ccfb935 100644 --- a/src/adcp/types/generated_poc/property/feature_requirement.py +++ b/src/adcp/types/generated_poc/property/feature_requirement.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/feature_requirement.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,20 +12,20 @@ class IfNotCovered(Enum): - exclude = "exclude" - include = "include" + exclude = 'exclude' + include = 'include' class FeatureRequirement(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) allowed_values: Annotated[ list[Any] | None, - Field(description="Values that pass the requirement (for binary/categorical features)"), + Field(description='Values that pass the requirement (for binary/categorical features)'), ] = None feature_id: Annotated[ - str, Field(description="Feature to evaluate (discovered via list_property_features)") + str, Field(description='Feature to evaluate (discovered via list_property_features)') ] if_not_covered: Annotated[ IfNotCovered | None, @@ -34,9 +34,9 @@ class FeatureRequirement(AdCPBaseModel): ), ] = IfNotCovered.exclude max_value: Annotated[ - float | None, Field(description="Maximum numeric value allowed (for quantitative features)") + float | None, Field(description='Maximum numeric value allowed (for quantitative features)') ] = None min_value: Annotated[ float | None, - Field(description="Minimum numeric value required (for quantitative features)"), + Field(description='Minimum numeric value required (for quantitative features)'), ] = None diff --git a/src/adcp/types/generated_poc/property/get_property_list_request.py b/src/adcp/types/generated_poc/property/get_property_list_request.py index 656c2808..79e1433d 100644 --- a/src/adcp/types/generated_poc/property/get_property_list_request.py +++ b/src/adcp/types/generated_poc/property/get_property_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/get_property_list_request.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,20 +15,20 @@ class GetPropertyListRequest(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) context: context_1.ContextObject | None = None - cursor: Annotated[str | None, Field(description="Pagination cursor for large result sets")] = ( + cursor: Annotated[str | None, Field(description='Pagination cursor for large result sets')] = ( None ) ext: ext_1.ExtensionObject | None = None - list_id: Annotated[str, Field(description="ID of the property list to retrieve")] + list_id: Annotated[str, Field(description='ID of the property list to retrieve')] max_results: Annotated[ - int | None, Field(description="Maximum identifiers to return (for large lists)", ge=1) + int | None, Field(description='Maximum identifiers to return (for large lists)', ge=1) ] = None resolve: Annotated[ bool | None, Field( - description="Whether to apply filters and return resolved identifiers (default: true)" + description='Whether to apply filters and return resolved identifiers (default: true)' ), ] = True diff --git a/src/adcp/types/generated_poc/property/get_property_list_response.py b/src/adcp/types/generated_poc/property/get_property_list_response.py index 9b5df6db..1649cfcf 100644 --- a/src/adcp/types/generated_poc/property/get_property_list_response.py +++ b/src/adcp/types/generated_poc/property/get_property_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/get_property_list_response.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,20 +16,20 @@ class Pagination(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) - cursor: Annotated[str | None, Field(description="Cursor for next page")] = None - has_more: Annotated[bool | None, Field(description="Whether more results are available")] = None + cursor: Annotated[str | None, Field(description='Cursor for next page')] = None + has_more: Annotated[bool | None, Field(description='Whether more results are available')] = None class GetPropertyListResponse(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) cache_valid_until: Annotated[ AwareDatetime | None, Field( - description="Cache expiration timestamp. Re-fetch the list after this time to get updated identifiers." + description='Cache expiration timestamp. Re-fetch the list after this time to get updated identifiers.' ), ] = None coverage_gaps: Annotated[ @@ -42,20 +42,20 @@ class GetPropertyListResponse(AdCPBaseModel): identifiers: Annotated[ list[identifier.Identifier] | None, Field( - description="Resolved identifiers that passed filters (if resolve=true). Cache these locally for real-time use." + description='Resolved identifiers that passed filters (if resolve=true). Cache these locally for real-time use.' ), ] = None list: Annotated[ property_list.PropertyList, - Field(description="The property list metadata (always returned)"), + Field(description='The property list metadata (always returned)'), ] - pagination: Annotated[Pagination | None, Field(description="Pagination information")] = None + pagination: Annotated[Pagination | None, Field(description='Pagination information')] = None resolved_at: Annotated[ - AwareDatetime | None, Field(description="When the list was resolved") + AwareDatetime | None, Field(description='When the list was resolved') ] = None returned_count: Annotated[ - int | None, Field(description="Number of identifiers returned in this response") + int | None, Field(description='Number of identifiers returned in this response') ] = None total_count: Annotated[ - int | None, Field(description="Total number of identifiers in resolved list") + int | None, Field(description='Total number of identifiers in resolved list') ] = None diff --git a/src/adcp/types/generated_poc/property/list_property_features_request.py b/src/adcp/types/generated_poc/property/list_property_features_request.py deleted file mode 100644 index 94665a09..00000000 --- a/src/adcp/types/generated_poc/property/list_property_features_request.py +++ /dev/null @@ -1,25 +0,0 @@ -# generated by datamodel-codegen: -# filename: property/list_property_features_request.json -# timestamp: 2026-01-14T17:08:13+00:00 - -from __future__ import annotations - -from typing import Annotated - -from adcp.types.base import AdCPBaseModel -from pydantic import ConfigDict, Field - -from ..core import ext as ext_1 - - -class ListPropertyFeaturesRequest(AdCPBaseModel): - model_config = ConfigDict( - extra="forbid", - ) - countries: Annotated[ - list[str] | None, Field(description="Filter to features available in these countries") - ] = None - ext: ext_1.ExtensionObject | None = None - property_types: Annotated[ - list[str] | None, Field(description="Filter to features available for these property types") - ] = None diff --git a/src/adcp/types/generated_poc/property/list_property_features_response.py b/src/adcp/types/generated_poc/property/list_property_features_response.py deleted file mode 100644 index b099f4aa..00000000 --- a/src/adcp/types/generated_poc/property/list_property_features_response.py +++ /dev/null @@ -1,24 +0,0 @@ -# generated by datamodel-codegen: -# filename: property/list_property_features_response.json -# timestamp: 2026-01-14T17:08:13+00:00 - -from __future__ import annotations - -from typing import Annotated - -from adcp.types.base import AdCPBaseModel -from pydantic import ConfigDict, Field - -from ..core import ext as ext_1 -from . import property_feature_definition - - -class ListPropertyFeaturesResponse(AdCPBaseModel): - model_config = ConfigDict( - extra="forbid", - ) - ext: ext_1.ExtensionObject | None = None - features: Annotated[ - list[property_feature_definition.PropertyFeatureDefinition], - Field(description="Features this agent can evaluate"), - ] diff --git a/src/adcp/types/generated_poc/property/list_property_lists_request.py b/src/adcp/types/generated_poc/property/list_property_lists_request.py index fabe6af2..d2ebb028 100644 --- a/src/adcp/types/generated_poc/property/list_property_lists_request.py +++ b/src/adcp/types/generated_poc/property/list_property_lists_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/list_property_lists_request.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,15 +15,15 @@ class ListPropertyListsRequest(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) context: context_1.ContextObject | None = None - cursor: Annotated[str | None, Field(description="Pagination cursor")] = None + cursor: Annotated[str | None, Field(description='Pagination cursor')] = None ext: ext_1.ExtensionObject | None = None - max_results: Annotated[int | None, Field(description="Maximum lists to return", ge=1)] = 100 + max_results: Annotated[int | None, Field(description='Maximum lists to return', ge=1)] = 100 name_contains: Annotated[ - str | None, Field(description="Filter to lists whose name contains this string") + str | None, Field(description='Filter to lists whose name contains this string') ] = None principal: Annotated[ - str | None, Field(description="Filter to lists owned by this principal") + str | None, Field(description='Filter to lists owned by this principal') ] = None diff --git a/src/adcp/types/generated_poc/property/list_property_lists_response.py b/src/adcp/types/generated_poc/property/list_property_lists_response.py index ba9c392c..693df004 100644 --- a/src/adcp/types/generated_poc/property/list_property_lists_response.py +++ b/src/adcp/types/generated_poc/property/list_property_lists_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/list_property_lists_response.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,25 +15,25 @@ class Pagination(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) - cursor: Annotated[str | None, Field(description="Cursor for next page")] = None - has_more: Annotated[bool | None, Field(description="Whether more results are available")] = None + cursor: Annotated[str | None, Field(description='Cursor for next page')] = None + has_more: Annotated[bool | None, Field(description='Whether more results are available')] = None class ListPropertyListsResponse(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) ext: ext_1.ExtensionObject | None = None lists: Annotated[ list[property_list.PropertyList], - Field(description="Array of property lists (metadata only, not resolved properties)"), + Field(description='Array of property lists (metadata only, not resolved properties)'), ] - pagination: Annotated[Pagination | None, Field(description="Pagination information")] = None + pagination: Annotated[Pagination | None, Field(description='Pagination information')] = None returned_count: Annotated[ - int | None, Field(description="Number of lists returned in this response") + int | None, Field(description='Number of lists returned in this response') ] = None total_count: Annotated[ - int | None, Field(description="Total number of lists matching criteria") + int | None, Field(description='Total number of lists matching criteria') ] = None diff --git a/src/adcp/types/generated_poc/property/property_error.py b/src/adcp/types/generated_poc/property/property_error.py index aeb92645..0b0856ca 100644 --- a/src/adcp/types/generated_poc/property/property_error.py +++ b/src/adcp/types/generated_poc/property/property_error.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/property_error.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,20 +14,20 @@ class Code(Enum): - PROPERTY_NOT_FOUND = "PROPERTY_NOT_FOUND" - PROPERTY_NOT_MONITORED = "PROPERTY_NOT_MONITORED" - LIST_NOT_FOUND = "LIST_NOT_FOUND" - LIST_ACCESS_DENIED = "LIST_ACCESS_DENIED" - METHODOLOGY_NOT_SUPPORTED = "METHODOLOGY_NOT_SUPPORTED" - JURISDICTION_NOT_SUPPORTED = "JURISDICTION_NOT_SUPPORTED" + PROPERTY_NOT_FOUND = 'PROPERTY_NOT_FOUND' + PROPERTY_NOT_MONITORED = 'PROPERTY_NOT_MONITORED' + LIST_NOT_FOUND = 'LIST_NOT_FOUND' + LIST_ACCESS_DENIED = 'LIST_ACCESS_DENIED' + METHODOLOGY_NOT_SUPPORTED = 'METHODOLOGY_NOT_SUPPORTED' + JURISDICTION_NOT_SUPPORTED = 'JURISDICTION_NOT_SUPPORTED' class PropertyError(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) - code: Annotated[Code, Field(description="Error code")] - message: Annotated[str, Field(description="Human-readable error message")] + code: Annotated[Code, Field(description='Error code')] + message: Annotated[str, Field(description='Human-readable error message')] property: Annotated[ - property_1.Property | None, Field(description="The property that caused the error") + property_1.Property | None, Field(description='The property that caused the error') ] = None diff --git a/src/adcp/types/generated_poc/property/property_feature.py b/src/adcp/types/generated_poc/property/property_feature.py index 6ebca903..8e6c489b 100644 --- a/src/adcp/types/generated_poc/property/property_feature.py +++ b/src/adcp/types/generated_poc/property/property_feature.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/property_feature.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,11 +12,11 @@ class PropertyFeature(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) - feature_id: Annotated[str, Field(description="Identifier for the feature being assessed")] + feature_id: Annotated[str, Field(description='Identifier for the feature being assessed')] source: Annotated[ str | None, - Field(description="Source of the feature data (e.g., app_store_privacy_label, tcf_string)"), + Field(description='Source of the feature data (e.g., app_store_privacy_label, tcf_string)'), ] = None - value: Annotated[str, Field(description="The feature value")] + value: Annotated[str, Field(description='The feature value')] diff --git a/src/adcp/types/generated_poc/property/property_feature_definition.py b/src/adcp/types/generated_poc/property/property_feature_definition.py index 88cc619a..cf8165f9 100644 --- a/src/adcp/types/generated_poc/property/property_feature_definition.py +++ b/src/adcp/types/generated_poc/property/property_feature_definition.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/property_feature_definition.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,42 +15,42 @@ class Coverage(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) countries: Annotated[ - list[str] | None, Field(description="Countries where this feature is available") + list[str] | None, Field(description='Countries where this feature is available') ] = None property_types: Annotated[ - list[str] | None, Field(description="Property types this feature applies to") + list[str] | None, Field(description='Property types this feature applies to') ] = None class Range(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) - max: Annotated[float, Field(description="Maximum value")] - min: Annotated[float, Field(description="Minimum value")] + max: Annotated[float, Field(description='Maximum value')] + min: Annotated[float, Field(description='Minimum value')] class Type(Enum): - binary = "binary" - quantitative = "quantitative" - categorical = "categorical" + binary = 'binary' + quantitative = 'quantitative' + categorical = 'categorical' class PropertyFeatureDefinition(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) allowed_values: Annotated[ - list[str] | None, Field(description="For categorical features, the set of valid values") + list[str] | None, Field(description='For categorical features, the set of valid values') ] = None coverage: Annotated[ - Coverage | None, Field(description="What this feature covers (empty arrays = all)") + Coverage | None, Field(description='What this feature covers (empty arrays = all)') ] = None description: Annotated[ - str | None, Field(description="Description of what this feature measures or represents") + str | None, Field(description='Description of what this feature measures or represents') ] = None ext: ext_1.ExtensionObject | None = None feature_id: Annotated[ @@ -62,19 +62,19 @@ class PropertyFeatureDefinition(AdCPBaseModel): methodology_url: Annotated[ AnyUrl, Field( - description="URL to documentation explaining how this feature is calculated/measured" + description='URL to documentation explaining how this feature is calculated/measured' ), ] methodology_version: Annotated[ - str | None, Field(description="Version identifier for the methodology (for audit trails)") + str | None, Field(description='Version identifier for the methodology (for audit trails)') ] = None - name: Annotated[str, Field(description="Human-readable name for the feature")] + name: Annotated[str, Field(description='Human-readable name for the feature')] range: Annotated[ - Range | None, Field(description="For quantitative features, the valid range of values") + Range | None, Field(description='For quantitative features, the valid range of values') ] = None type: Annotated[ Type, Field( - description="The type of values this feature produces: binary (true/false), quantitative (numeric range), categorical (enumerated values)" + description='The type of values this feature produces: binary (true/false), quantitative (numeric range), categorical (enumerated values)' ), ] diff --git a/src/adcp/types/generated_poc/property/property_list.py b/src/adcp/types/generated_poc/property/property_list.py index e3d1e05f..51dab408 100644 --- a/src/adcp/types/generated_poc/property/property_list.py +++ b/src/adcp/types/generated_poc/property/property_list.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/property_list.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,7 +15,7 @@ class PropertyList(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) base_properties: Annotated[ list[base_property_source.BasePropertySource] | None, @@ -25,16 +25,16 @@ class PropertyList(AdCPBaseModel): ] = None brand_manifest: Annotated[ brand_manifest_1.BrandManifest | None, - Field(description="Brand identity used to automatically apply appropriate rules"), + Field(description='Brand identity used to automatically apply appropriate rules'), ] = None cache_duration_hours: Annotated[ int | None, Field( - description="Recommended cache duration for resolved list. Consumers should re-fetch after this period.", + description='Recommended cache duration for resolved list. Consumers should re-fetch after this period.', ge=1, ), ] = 24 - created_at: Annotated[AwareDatetime | None, Field(description="When the list was created")] = ( + created_at: Annotated[AwareDatetime | None, Field(description='When the list was created')] = ( None ) description: Annotated[str | None, Field(description="Description of the list's purpose")] = ( @@ -42,21 +42,21 @@ class PropertyList(AdCPBaseModel): ) filters: Annotated[ property_list_filters.PropertyListFilters | None, - Field(description="Dynamic filters applied when resolving the list"), + Field(description='Dynamic filters applied when resolving the list'), ] = None - list_id: Annotated[str, Field(description="Unique identifier for this property list")] - name: Annotated[str, Field(description="Human-readable name for the list")] + list_id: Annotated[str, Field(description='Unique identifier for this property list')] + name: Annotated[str, Field(description='Human-readable name for the list')] principal: Annotated[ - str | None, Field(description="Principal identity that owns this list") + str | None, Field(description='Principal identity that owns this list') ] = None property_count: Annotated[ int | None, - Field(description="Number of properties in the resolved list (at time of last resolution)"), + Field(description='Number of properties in the resolved list (at time of last resolution)'), ] = None updated_at: Annotated[ - AwareDatetime | None, Field(description="When the list was last modified") + AwareDatetime | None, Field(description='When the list was last modified') ] = None webhook_url: Annotated[ AnyUrl | None, - Field(description="URL to receive notifications when the resolved list changes"), + Field(description='URL to receive notifications when the resolved list changes'), ] = None diff --git a/src/adcp/types/generated_poc/property/property_list_changed_webhook.py b/src/adcp/types/generated_poc/property/property_list_changed_webhook.py index baec0a5d..00cf8bfa 100644 --- a/src/adcp/types/generated_poc/property/property_list_changed_webhook.py +++ b/src/adcp/types/generated_poc/property/property_list_changed_webhook.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/property_list_changed_webhook.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -14,35 +14,35 @@ class ChangeSummary(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) properties_added: Annotated[ - int | None, Field(description="Number of properties added since last resolution") + int | None, Field(description='Number of properties added since last resolution') ] = None properties_removed: Annotated[ - int | None, Field(description="Number of properties removed since last resolution") + int | None, Field(description='Number of properties removed since last resolution') ] = None total_properties: Annotated[ - int | None, Field(description="Total properties in the resolved list") + int | None, Field(description='Total properties in the resolved list') ] = None class PropertyListChangedWebhook(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) cache_valid_until: Annotated[ AwareDatetime | None, - Field(description="When the consumer should refresh from the governance agent"), + Field(description='When the consumer should refresh from the governance agent'), ] = None change_summary: Annotated[ - ChangeSummary | None, Field(description="Summary of changes to the resolved list") + ChangeSummary | None, Field(description='Summary of changes to the resolved list') ] = None - event: Annotated[Literal["property_list_changed"], Field(description="The event type")] + event: Annotated[Literal['property_list_changed'], Field(description='The event type')] ext: ext_1.ExtensionObject | None = None - list_id: Annotated[str, Field(description="ID of the property list that changed")] - list_name: Annotated[str | None, Field(description="Name of the property list")] = None - resolved_at: Annotated[AwareDatetime, Field(description="When the list was re-resolved")] + list_id: Annotated[str, Field(description='ID of the property list that changed')] + list_name: Annotated[str | None, Field(description='Name of the property list')] = None + resolved_at: Annotated[AwareDatetime, Field(description='When the list was re-resolved')] signature: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/property/property_list_filters.py b/src/adcp/types/generated_poc/property/property_list_filters.py index 4b5dd305..928a03d9 100644 --- a/src/adcp/types/generated_poc/property/property_list_filters.py +++ b/src/adcp/types/generated_poc/property/property_list_filters.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/property_list_filters.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,33 +15,33 @@ class CountriesAllItem(RootModel[str]): - root: Annotated[str, Field(pattern="^[A-Z]{2}$")] + root: Annotated[str, Field(pattern='^[A-Z]{2}$')] class PropertyListFilters(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) channels_any: Annotated[ - list[channels.AdvertisingChannels], - Field(description="Property must support ANY of the listed channels. Required."), + list[channels.MediaChannel], + Field(description='Property must support ANY of the listed channels. Required.'), ] countries_all: Annotated[ list[CountriesAllItem], Field( - description="Property must have feature data for ALL listed countries (ISO codes). Required." + description='Property must have feature data for ALL listed countries (ISO codes). Required.' ), ] exclude_identifiers: Annotated[ list[identifier.Identifier] | None, - Field(description="Identifiers to always exclude from results"), + Field(description='Identifiers to always exclude from results'), ] = None feature_requirements: Annotated[ list[feature_requirement.FeatureRequirement] | None, Field( - description="Feature-based requirements. Property must pass ALL requirements (AND logic)." + description='Feature-based requirements. Property must pass ALL requirements (AND logic).' ), ] = None property_types: Annotated[ - list[property_type.PropertyType] | None, Field(description="Filter to these property types") + list[property_type.PropertyType] | None, Field(description='Filter to these property types') ] = None diff --git a/src/adcp/types/generated_poc/property/update_property_list_request.py b/src/adcp/types/generated_poc/property/update_property_list_request.py index a5028ba2..7f7e9814 100644 --- a/src/adcp/types/generated_poc/property/update_property_list_request.py +++ b/src/adcp/types/generated_poc/property/update_property_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/update_property_list_request.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,30 +17,30 @@ class UpdatePropertyListRequest(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) base_properties: Annotated[ list[base_property_source.BasePropertySource] | None, Field( - description="Complete replacement for the base properties list (not a patch). Each entry is a discriminated union: publisher_tags (publisher_domain + tags), publisher_ids (publisher_domain + property_ids), or identifiers (direct identifiers)." + description='Complete replacement for the base properties list (not a patch). Each entry is a discriminated union: publisher_tags (publisher_domain + tags), publisher_ids (publisher_domain + property_ids), or identifiers (direct identifiers).' ), ] = None brand_manifest: Annotated[ brand_manifest_1.BrandManifest | None, - Field(description="Update brand identity and requirements"), + Field(description='Update brand identity and requirements'), ] = None context: context_1.ContextObject | None = None - description: Annotated[str | None, Field(description="New description")] = None + description: Annotated[str | None, Field(description='New description')] = None ext: ext_1.ExtensionObject | None = None filters: Annotated[ property_list_filters.PropertyListFilters | None, - Field(description="Complete replacement for the filters (not a patch)"), + Field(description='Complete replacement for the filters (not a patch)'), ] = None - list_id: Annotated[str, Field(description="ID of the property list to update")] - name: Annotated[str | None, Field(description="New name for the list")] = None + list_id: Annotated[str, Field(description='ID of the property list to update')] + name: Annotated[str | None, Field(description='New name for the list')] = None webhook_url: Annotated[ AnyUrl | None, Field( - description="Update the webhook URL for list change notifications (set to empty string to remove)" + description='Update the webhook URL for list change notifications (set to empty string to remove)' ), ] = None diff --git a/src/adcp/types/generated_poc/property/update_property_list_response.py b/src/adcp/types/generated_poc/property/update_property_list_response.py index e8bf8875..1cf4cb47 100644 --- a/src/adcp/types/generated_poc/property/update_property_list_response.py +++ b/src/adcp/types/generated_poc/property/update_property_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/update_property_list_response.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -15,7 +15,7 @@ class UpdatePropertyListResponse(AdCPBaseModel): model_config = ConfigDict( - extra="forbid", + extra='forbid', ) ext: ext_1.ExtensionObject | None = None - list: Annotated[property_list.PropertyList, Field(description="The updated property list")] + list: Annotated[property_list.PropertyList, Field(description='The updated property list')] diff --git a/src/adcp/types/generated_poc/protocol/__init__.py b/src/adcp/types/generated_poc/protocol/__init__.py new file mode 100644 index 00000000..93575326 --- /dev/null +++ b/src/adcp/types/generated_poc/protocol/__init__.py @@ -0,0 +1,3 @@ +# generated by datamodel-codegen: +# filename: .schema_temp +# timestamp: 2026-01-25T21:17:54+00:00 diff --git a/src/adcp/types/generated_poc/protocol/get_adcp_capabilities_request.py b/src/adcp/types/generated_poc/protocol/get_adcp_capabilities_request.py new file mode 100644 index 00000000..177e78d8 --- /dev/null +++ b/src/adcp/types/generated_poc/protocol/get_adcp_capabilities_request.py @@ -0,0 +1,34 @@ +# generated by datamodel-codegen: +# filename: protocol/get_adcp_capabilities_request.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field + +from ..core import context as context_1 +from ..core import ext as ext_1 + + +class Protocol(Enum): + media_buy = 'media_buy' + signals = 'signals' + sponsored_intelligence = 'sponsored_intelligence' + + +class GetAdcpCapabilitiesRequest(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + context: context_1.ContextObject | None = None + ext: ext_1.ExtensionObject | None = None + protocols: Annotated[ + list[Protocol] | None, + Field( + description='Specific protocols to query capabilities for. If omitted, returns capabilities for all supported protocols.' + ), + ] = None diff --git a/src/adcp/types/generated_poc/protocol/get_adcp_capabilities_response.py b/src/adcp/types/generated_poc/protocol/get_adcp_capabilities_response.py new file mode 100644 index 00000000..0897bf85 --- /dev/null +++ b/src/adcp/types/generated_poc/protocol/get_adcp_capabilities_response.py @@ -0,0 +1,353 @@ +# generated by datamodel-codegen: +# filename: protocol/get_adcp_capabilities_response.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import AnyUrl, AwareDatetime, ConfigDict, Field, RootModel + +from ..core import context as context_1 +from ..core import error +from ..core import ext as ext_1 +from ..core import media_buy_features +from ..enums import channels +from ..sponsored_intelligence import si_capabilities + + +class MajorVersion(RootModel[int]): + root: Annotated[int, Field(ge=1)] + + +class Adcp(AdCPBaseModel): + major_versions: Annotated[ + list[MajorVersion], + Field( + description='AdCP major versions supported by this seller. Major versions indicate breaking changes.', + min_length=1, + ), + ] + + +class ExtensionsSupportedItem(RootModel[str]): + root: Annotated[ + str, + Field( + description="Extension namespace (lowercase alphanumeric with underscores, e.g., 'scope3', 'garm', 'iab_tcf')", + pattern='^[a-z][a-z0-9_]*$', + ), + ] + + +class Range(AdCPBaseModel): + max: Annotated[float, Field(description='Maximum value')] + min: Annotated[float, Field(description='Minimum value')] + + +class Type(Enum): + binary = 'binary' + quantitative = 'quantitative' + categorical = 'categorical' + + +class PropertyFeature(AdCPBaseModel): + categories: Annotated[ + list[str] | None, Field(description='For categorical features, the valid values') + ] = None + description: Annotated[ + str | None, Field(description='Human-readable description of what this feature measures') + ] = None + feature_id: Annotated[ + str, + Field( + description="Unique identifier for this feature (e.g., 'consent_quality', 'coppa_certified', 'carbon_score')" + ), + ] + methodology_url: Annotated[ + AnyUrl | None, + Field( + description='URL to documentation explaining how this feature is calculated or measured. Helps buyers understand and compare methodologies across vendors.' + ), + ] = None + range: Annotated[ + Range | None, Field(description='For quantitative features, the valid range') + ] = None + type: Annotated[ + Type, + Field( + description="Data type: 'binary' for yes/no, 'quantitative' for numeric scores, 'categorical' for enum values" + ), + ] + + +class Governance(AdCPBaseModel): + property_features: Annotated[ + list[PropertyFeature] | None, + Field( + description='Property features this governance agent can evaluate. Each feature describes a score, rating, or certification the agent can provide for properties.' + ), + ] = None + + +class MraidVersion(RootModel[str]): + root: Annotated[str, Field(pattern='^[0-9]+\\.[0-9]+$')] + + +class VastVersion(MraidVersion): + pass + + +class CreativeSpecs(AdCPBaseModel): + mraid_versions: Annotated[ + list[MraidVersion] | None, + Field(description='MRAID versions supported for rich media mobile creatives'), + ] = None + simid: Annotated[bool | None, Field(description='SIMID support for interactive video ads')] = ( + None + ) + vast_versions: Annotated[ + list[VastVersion] | None, Field(description='VAST versions supported for video creatives') + ] = None + vpaid: Annotated[bool | None, Field(description='VPAID support for interactive video ads')] = ( + None + ) + + +class GeoMetros(AdCPBaseModel): + eurostat_nuts2: Annotated[ + bool | None, Field(description='Supports Eurostat NUTS Level 2 regions (EU)') + ] = None + nielsen_dma: Annotated[ + bool | None, + Field(description="Supports Nielsen DMA codes (US market, e.g., '501' for NYC)"), + ] = None + uk_itl1: Annotated[bool | None, Field(description='Supports UK ITL Level 1 regions')] = None + uk_itl2: Annotated[bool | None, Field(description='Supports UK ITL Level 2 regions')] = None + + +class GeoPostalAreas(AdCPBaseModel): + au_postcode: Annotated[ + bool | None, Field(description="Australian postcode, 4 digits (e.g., '2000')") + ] = None + ca_fsa: Annotated[ + bool | None, Field(description="Canadian Forward Sortation Area (e.g., 'K1A')") + ] = None + ca_full: Annotated[ + bool | None, Field(description="Canadian full postal code (e.g., 'K1A 0B1')") + ] = None + de_plz: Annotated[ + bool | None, Field(description="German Postleitzahl, 5 digits (e.g., '10115')") + ] = None + fr_code_postal: Annotated[ + bool | None, Field(description="French code postal, 5 digits (e.g., '75001')") + ] = None + gb_full: Annotated[bool | None, Field(description="UK full postcode (e.g., 'SW1A 1AA')")] = None + gb_outward: Annotated[ + bool | None, Field(description="UK postcode district / outward code (e.g., 'SW1', 'EC1')") + ] = None + us_zip: Annotated[bool | None, Field(description="US 5-digit ZIP codes (e.g., '10001')")] = None + us_zip_plus_four: Annotated[ + bool | None, Field(description="US 9-digit ZIP+4 codes (e.g., '10001-1234')") + ] = None + + +class Targeting(AdCPBaseModel): + geo_countries: Annotated[ + bool | None, + Field( + description="Supports country-level geo targeting using ISO 3166-1 alpha-2 codes (e.g., 'US', 'GB', 'DE')" + ), + ] = None + geo_metros: Annotated[ + GeoMetros | None, + Field( + description='Metro area targeting support. Specifies which classification systems are supported.' + ), + ] = None + geo_postal_areas: Annotated[ + GeoPostalAreas | None, + Field( + description='Postal area targeting support. Specifies which postal code systems are supported. System names encode country and precision.' + ), + ] = None + geo_regions: Annotated[ + bool | None, + Field( + description="Supports region/state-level geo targeting using ISO 3166-2 subdivision codes (e.g., 'US-NY', 'GB-SCT', 'DE-BY')" + ), + ] = None + + +class Execution(AdCPBaseModel): + axe_integrations: Annotated[ + list[AnyUrl] | None, + Field( + description='Agentic ad exchange (AXE) integrations supported. URLs are canonical identifiers for exchanges this seller can execute through.' + ), + ] = None + creative_specs: Annotated[ + CreativeSpecs | None, Field(description='Creative specification support') + ] = None + targeting: Annotated[ + Targeting | None, + Field( + description='Targeting capabilities. If declared true/supported, buyer can use these targeting parameters and seller MUST honor them.' + ), + ] = None + + +class PrimaryCountry(RootModel[str]): + root: Annotated[str, Field(pattern='^[A-Z]{2}$')] + + +class PublisherDomain(RootModel[str]): + root: Annotated[ + str, Field(pattern='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$') + ] + + +class Portfolio(AdCPBaseModel): + advertising_policies: Annotated[ + str | None, + Field( + description='Advertising content policies, restrictions, and guidelines', + max_length=10000, + ), + ] = None + description: Annotated[ + str | None, + Field( + description='Markdown-formatted description of the inventory portfolio', max_length=5000 + ), + ] = None + primary_channels: Annotated[ + list[channels.MediaChannel] | None, + Field(description='Primary advertising channels in this portfolio'), + ] = None + primary_countries: Annotated[ + list[PrimaryCountry] | None, + Field(description='Primary countries (ISO 3166-1 alpha-2) where inventory is concentrated'), + ] = None + publisher_domains: Annotated[ + list[PublisherDomain], + Field( + description="Publisher domains this seller is authorized to represent. Buyers should fetch each publisher's adagents.json for property definitions.", + min_length=1, + ), + ] + + +class Signals(AdCPBaseModel): + features: Annotated[ + dict[str, bool] | None, Field(description='Optional signals features supported') + ] = None + + +class Preferred(Enum): + mcp = 'mcp' + a2a = 'a2a' + + +class Transport(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + type: Annotated[Preferred, Field(description='Protocol transport type')] + url: Annotated[AnyUrl, Field(description='Agent endpoint URL for this transport')] + + +class Endpoint(AdCPBaseModel): + preferred: Annotated[ + Preferred | None, Field(description='Preferred transport when host supports multiple') + ] = None + transports: Annotated[ + list[Transport], + Field( + description='Available protocol transports. Hosts select based on their capabilities.', + min_length=1, + ), + ] + + +class SupportedProtocol(Enum): + media_buy = 'media_buy' + signals = 'signals' + governance = 'governance' + sponsored_intelligence = 'sponsored_intelligence' + + +class MediaBuy(AdCPBaseModel): + execution: Annotated[ + Execution | None, Field(description='Technical execution capabilities for media buying') + ] = None + features: media_buy_features.MediaBuyFeatures | None = None + portfolio: Annotated[ + Portfolio | None, + Field(description="Information about the seller's media inventory portfolio"), + ] = None + + +class SponsoredIntelligence(AdCPBaseModel): + brand_manifest_url: Annotated[ + AnyUrl | None, Field(description='URL to brand manifest with colors, fonts, logos, tone') + ] = None + capabilities: Annotated[ + si_capabilities.SiCapabilities, + Field(description='Modalities, components, and commerce capabilities'), + ] + endpoint: Annotated[Endpoint, Field(description='SI agent endpoint configuration')] + + +class GetAdcpCapabilitiesResponse(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + adcp: Annotated[Adcp, Field(description='Core AdCP protocol information')] + context: context_1.ContextObject | None = None + errors: Annotated[ + list[error.Error] | None, Field(description='Task-specific errors and warnings') + ] = None + ext: ext_1.ExtensionObject | None = None + extensions_supported: Annotated[ + list[ExtensionsSupportedItem] | None, + Field( + description='Extension namespaces this agent supports. Buyers can expect meaningful data in ext.{namespace} fields on responses from this agent. Extension schemas are published in the AdCP extension registry.' + ), + ] = None + governance: Annotated[ + Governance | None, + Field( + description='Governance protocol capabilities. Only present if governance is in supported_protocols. Governance agents provide property data like compliance scores, brand safety ratings, and sustainability metrics.' + ), + ] = None + last_updated: Annotated[ + AwareDatetime | None, + Field( + description='ISO 8601 timestamp of when capabilities were last updated. Buyers can use this for cache invalidation.' + ), + ] = None + media_buy: Annotated[ + MediaBuy | None, + Field( + description='Media-buy protocol capabilities. Only present if media_buy is in supported_protocols.' + ), + ] = None + signals: Annotated[ + Signals | None, + Field( + description='Signals protocol capabilities. Only present if signals is in supported_protocols. Reserved for future use.' + ), + ] = None + sponsored_intelligence: Annotated[ + SponsoredIntelligence | None, + Field( + description='Sponsored Intelligence protocol capabilities. Only present if sponsored_intelligence is in supported_protocols. SI agents handle conversational brand experiences.' + ), + ] = None + supported_protocols: Annotated[ + list[SupportedProtocol], + Field(description='Which AdCP domain protocols this seller supports', min_length=1), + ] diff --git a/src/adcp/types/generated_poc/protocols/adcp_extension.py b/src/adcp/types/generated_poc/protocols/adcp_extension.py index f410049d..b1d30d52 100644 --- a/src/adcp/types/generated_poc/protocols/adcp_extension.py +++ b/src/adcp/types/generated_poc/protocols/adcp_extension.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: protocols/adcp_extension.json -# timestamp: 2026-01-14T17:08:13+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -12,42 +12,39 @@ class ExtensionsSupportedItem(RootModel[str]): - root: Annotated[ - str, - Field( - description="Extension namespace (e.g., 'sustainability'). Must be lowercase alphanumeric with underscores.", - pattern="^[a-z][a-z0-9_]*$", - ), - ] + root: Annotated[str, Field(pattern='^[a-z][a-z0-9_]*$')] class ProtocolsSupportedEnum(Enum): - media_buy = "media_buy" - creative = "creative" - signals = "signals" + media_buy = 'media_buy' + creative = 'creative' + signals = 'signals' -class AdcpAgentCardExtensionParams(AdCPBaseModel): +class AdcpAgentCardExtensionParamsDeprecated(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) adcp_version: Annotated[ str, Field( - description="Semantic version of the AdCP specification this agent implements (e.g., '2.5.0'). Extension schemas are versioned along with the AdCP spec.", - pattern="^\\d+\\.\\d+\\.\\d+$", + deprecated=True, + description='DEPRECATED: Use get_adcp_capabilities response adcp.major_versions instead.', + pattern='^\\d+\\.\\d+\\.\\d+$', ), ] extensions_supported: Annotated[ list[ExtensionsSupportedItem] | None, Field( - description="Typed extensions this agent supports. Each extension has a formal schema in /schemas/extensions/. Extension version is determined by adcp_version." + deprecated=True, + description='DEPRECATED: Typed extensions can be declared in get_adcp_capabilities ext field.', ), ] = None protocols_supported: Annotated[ list[ProtocolsSupportedEnum], Field( - description="AdCP protocol domains supported by this agent. At least one must be specified.", + deprecated=True, + description='DEPRECATED: Use get_adcp_capabilities response supported_protocols instead.', min_length=1, ), ] diff --git a/src/adcp/types/generated_poc/signals/activate_signal_request.py b/src/adcp/types/generated_poc/signals/activate_signal_request.py index 91610a7a..fd7b849d 100644 --- a/src/adcp/types/generated_poc/signals/activate_signal_request.py +++ b/src/adcp/types/generated_poc/signals/activate_signal_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: signals/activate_signal_request.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,17 +16,17 @@ class ActivateSignalRequest(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None deployments: Annotated[ list[destination.Destination], Field( - description="Target deployment(s) for activation. If the authenticated caller matches one of these deployment targets, activation keys will be included in the response.", + description='Target deployment(s) for activation. If the authenticated caller matches one of these deployment targets, activation keys will be included in the response.', min_length=1, ), ] ext: ext_1.ExtensionObject | None = None signal_agent_segment_id: Annotated[ - str, Field(description="The universal identifier for the signal to activate") + str, Field(description='The universal identifier for the signal to activate') ] diff --git a/src/adcp/types/generated_poc/signals/activate_signal_response.py b/src/adcp/types/generated_poc/signals/activate_signal_response.py index 9d9e0629..6326395a 100644 --- a/src/adcp/types/generated_poc/signals/activate_signal_response.py +++ b/src/adcp/types/generated_poc/signals/activate_signal_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: signals/activate_signal_response.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,25 +16,25 @@ class ActivateSignalResponse1(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None deployments: Annotated[ list[deployment.Deployment], - Field(description="Array of deployment results for each deployment target"), + Field(description='Array of deployment results for each deployment target'), ] ext: ext_1.ExtensionObject | None = None class ActivateSignalResponse2(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ list[error.Error], Field( - description="Array of errors explaining why activation failed (e.g., platform connectivity issues, signal definition problems, authentication failures)", + description='Array of errors explaining why activation failed (e.g., platform connectivity issues, signal definition problems, authentication failures)', min_length=1, ), ] @@ -45,7 +45,7 @@ class ActivateSignalResponse(RootModel[ActivateSignalResponse1 | ActivateSignalR root: Annotated[ ActivateSignalResponse1 | ActivateSignalResponse2, Field( - description="Response payload for activate_signal task. Returns either complete success data OR error information, never both. This enforces atomic operation semantics - the signal is either fully activated or not activated at all.", - title="Activate Signal Response", + description='Response payload for activate_signal task. Returns either complete success data OR error information, never both. This enforces atomic operation semantics - the signal is either fully activated or not activated at all.', + title='Activate Signal Response', ), ] diff --git a/src/adcp/types/generated_poc/signals/get_signals_request.py b/src/adcp/types/generated_poc/signals/get_signals_request.py index 7ba5e512..395034d3 100644 --- a/src/adcp/types/generated_poc/signals/get_signals_request.py +++ b/src/adcp/types/generated_poc/signals/get_signals_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: signals/get_signals_request.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -16,20 +16,20 @@ class Country(RootModel[str]): - root: Annotated[str, Field(pattern="^[A-Z]{2}$")] + root: Annotated[str, Field(pattern='^[A-Z]{2}$')] class DeliverTo(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) countries: Annotated[ - list[Country], Field(description="Countries where signals will be used (ISO codes)") + list[Country], Field(description='Countries where signals will be used (ISO codes)') ] deployments: Annotated[ list[destination.Destination], Field( - description="List of deployment targets (DSPs, sales agents, etc.). If the authenticated caller matches one of these deployment targets, activation keys will be included in the response.", + description='List of deployment targets (DSPs, sales agents, etc.). If the authenticated caller matches one of these deployment targets, activation keys will be included in the response.', min_length=1, ), ] @@ -37,17 +37,17 @@ class DeliverTo(AdCPBaseModel): class GetSignalsRequest(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None deliver_to: Annotated[ - DeliverTo, Field(description="Deployment targets where signals need to be activated") + DeliverTo, Field(description='Deployment targets where signals need to be activated') ] ext: ext_1.ExtensionObject | None = None filters: signal_filters.SignalFilters | None = None max_results: Annotated[ - int | None, Field(description="Maximum number of results to return", ge=1) + int | None, Field(description='Maximum number of results to return', ge=1) ] = None signal_spec: Annotated[ - str, Field(description="Natural language description of the desired signals") + str, Field(description='Natural language description of the desired signals') ] diff --git a/src/adcp/types/generated_poc/signals/get_signals_response.py b/src/adcp/types/generated_poc/signals/get_signals_response.py index 4eb3a975..fdde8713 100644 --- a/src/adcp/types/generated_poc/signals/get_signals_response.py +++ b/src/adcp/types/generated_poc/signals/get_signals_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: signals/get_signals_response.json -# timestamp: 2026-01-08T19:25:24+00:00 +# timestamp: 2026-01-25T21:17:54+00:00 from __future__ import annotations @@ -17,42 +17,42 @@ class Pricing(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) - cpm: Annotated[float, Field(description="Cost per thousand impressions", ge=0.0)] - currency: Annotated[str, Field(description="Currency code", pattern="^[A-Z]{3}$")] + cpm: Annotated[float, Field(description='Cost per thousand impressions', ge=0.0)] + currency: Annotated[str, Field(description='Currency code', pattern='^[A-Z]{3}$')] class Signal(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) coverage_percentage: Annotated[ - float, Field(description="Percentage of audience coverage", ge=0.0, le=100.0) + float, Field(description='Percentage of audience coverage', ge=0.0, le=100.0) ] - data_provider: Annotated[str, Field(description="Name of the data provider")] + data_provider: Annotated[str, Field(description='Name of the data provider')] deployments: Annotated[ - list[deployment.Deployment], Field(description="Array of deployment targets") + list[deployment.Deployment], Field(description='Array of deployment targets') ] - description: Annotated[str, Field(description="Detailed signal description")] - name: Annotated[str, Field(description="Human-readable signal name")] - pricing: Annotated[Pricing, Field(description="Pricing information")] - signal_agent_segment_id: Annotated[str, Field(description="Unique identifier for the signal")] + description: Annotated[str, Field(description='Detailed signal description')] + name: Annotated[str, Field(description='Human-readable signal name')] + pricing: Annotated[Pricing, Field(description='Pricing information')] + signal_agent_segment_id: Annotated[str, Field(description='Unique identifier for the signal')] signal_type: Annotated[ - signal_catalog_type.SignalCatalogType, Field(description="Type of signal") + signal_catalog_type.SignalCatalogType, Field(description='Type of signal') ] class GetSignalsResponse(AdCPBaseModel): model_config = ConfigDict( - extra="allow", + extra='allow', ) context: context_1.ContextObject | None = None errors: Annotated[ list[error.Error] | None, Field( - description="Task-specific errors and warnings (e.g., signal discovery or pricing issues)" + description='Task-specific errors and warnings (e.g., signal discovery or pricing issues)' ), ] = None ext: ext_1.ExtensionObject | None = None - signals: Annotated[list[Signal], Field(description="Array of matching signals")] + signals: Annotated[list[Signal], Field(description='Array of matching signals')] diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/__init__.py b/src/adcp/types/generated_poc/sponsored_intelligence/__init__.py new file mode 100644 index 00000000..93575326 --- /dev/null +++ b/src/adcp/types/generated_poc/sponsored_intelligence/__init__.py @@ -0,0 +1,3 @@ +# generated by datamodel-codegen: +# filename: .schema_temp +# timestamp: 2026-01-25T21:17:54+00:00 diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_capabilities.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_capabilities.py new file mode 100644 index 00000000..68bf75e6 --- /dev/null +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_capabilities.py @@ -0,0 +1,102 @@ +# generated by datamodel-codegen: +# filename: sponsored_intelligence/si_capabilities.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated, Any + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field + + +class Commerce(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + acp_checkout: Annotated[ + bool | None, Field(description='Supports ACP (Agentic Commerce Protocol) checkout handoff') + ] = None + + +class StandardEnum(Enum): + text = 'text' + link = 'link' + image = 'image' + product_card = 'product_card' + carousel = 'carousel' + action_button = 'action_button' + + +class Components(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + extensions: Annotated[ + dict[str, Any] | None, + Field(description='Platform-specific extensions (chatgpt_apps_sdk, maps, forms, etc.)'), + ] = None + standard: Annotated[ + list[StandardEnum] | None, + Field(description='Standard components that all SI hosts must render'), + ] = None + + +class Avatar(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + avatar_id: Annotated[str | None, Field(description='Brand avatar identifier')] = None + provider: Annotated[ + str | None, Field(description='Avatar provider (d-id, heygen, synthesia, etc.)') + ] = None + + +class Video(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + formats: Annotated[ + list[str] | None, Field(description='Supported video formats (mp4, webm, etc.)') + ] = None + max_duration_seconds: Annotated[int | None, Field(description='Maximum video duration')] = None + + +class Voice(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + provider: Annotated[ + str | None, Field(description='TTS provider (elevenlabs, openai, etc.)') + ] = None + voice_id: Annotated[str | None, Field(description='Brand voice identifier')] = None + + +class Modalities(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + avatar: Annotated[ + bool | Avatar | None, Field(description='Animated video presence with brand avatar') + ] = None + conversational: Annotated[ + bool | None, Field(description='Pure text exchange - the baseline modality') + ] = True + video: Annotated[bool | Video | None, Field(description='Brand video content playback')] = None + voice: Annotated[ + bool | Voice | None, Field(description='Audio-based interaction using brand voice') + ] = None + + +class SiCapabilities(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + commerce: Annotated[Commerce | None, Field(description='Commerce capabilities')] = None + components: Annotated[Components | None, Field(description='Visual components supported')] = ( + None + ) + modalities: Annotated[ + Modalities | None, Field(description='Interaction modalities supported') + ] = None diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_get_offering_request.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_get_offering_request.py new file mode 100644 index 00000000..fb821430 --- /dev/null +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_get_offering_request.py @@ -0,0 +1,34 @@ +# generated by datamodel-codegen: +# filename: sponsored_intelligence/si_get_offering_request.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field + +from ..core import ext as ext_1 + + +class SiGetOfferingRequest(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + context: Annotated[ + str | None, + Field( + description="Optional natural language context about user intent for personalized results (e.g., 'mens size 14 near Cincinnati'). Must be anonymous - no PII." + ), + ] = None + ext: ext_1.ExtensionObject | None = None + include_products: Annotated[ + bool | None, Field(description='Whether to include matching products in the response') + ] = False + offering_id: Annotated[ + str, Field(description='Offering identifier from promoted offerings to get details for') + ] + product_limit: Annotated[ + int | None, Field(description='Maximum number of matching products to return', ge=1, le=50) + ] = 5 diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_get_offering_response.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_get_offering_response.py new file mode 100644 index 00000000..8adc0044 --- /dev/null +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_get_offering_response.py @@ -0,0 +1,100 @@ +# generated by datamodel-codegen: +# filename: sponsored_intelligence/si_get_offering_response.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import AnyUrl, AwareDatetime, ConfigDict, Field + +from ..core import error +from ..core import ext as ext_1 + + +class MatchingProduct(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + availability_summary: Annotated[ + str | None, + Field( + description="Brief availability info (e.g., 'In stock', 'Size 14 available', '3 left')" + ), + ] = None + image_url: Annotated[AnyUrl | None, Field(description='Product image')] = None + name: Annotated[str, Field(description='Product name')] + original_price: Annotated[str | None, Field(description='Original price if on sale')] = None + price: Annotated[str | None, Field(description="Display price (e.g., '$129', '$89.99')")] = None + product_id: Annotated[str, Field(description='Product identifier')] + url: Annotated[AnyUrl | None, Field(description='Product detail page URL')] = None + + +class Offering(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + expires_at: Annotated[AwareDatetime | None, Field(description='When this offering expires')] = ( + None + ) + image_url: Annotated[AnyUrl | None, Field(description='Hero image for the offering')] = None + landing_url: Annotated[AnyUrl | None, Field(description='Landing page URL')] = None + offering_id: Annotated[str | None, Field(description='Offering identifier')] = None + price_hint: Annotated[ + str | None, Field(description="Price indication (e.g., 'from $199', '50% off')") + ] = None + summary: Annotated[str | None, Field(description='Brief summary of the offering')] = None + tagline: Annotated[str | None, Field(description='Short promotional tagline')] = None + title: Annotated[str | None, Field(description='Offering title')] = None + + +class SiGetOfferingResponse(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + alternative_offering_ids: Annotated[ + list[str] | None, + Field(description='Alternative offerings to consider if this one is unavailable'), + ] = None + available: Annotated[bool, Field(description='Whether the offering is currently available')] + checked_at: Annotated[ + AwareDatetime | None, Field(description='When this offering information was retrieved') + ] = None + errors: Annotated[ + list[error.Error] | None, Field(description='Errors during offering lookup') + ] = None + ext: ext_1.ExtensionObject | None = None + matching_products: Annotated[ + list[MatchingProduct] | None, + Field( + description='Products matching the request context. Only included if include_products was true.' + ), + ] = None + offering: Annotated[Offering | None, Field(description='Offering details')] = None + offering_token: Annotated[ + str | None, + Field( + description="Token to pass to si_initiate_session for session continuity. Brand stores the full query context server-side (products shown, order, context) so they can resolve references like 'the second one' when the session starts." + ), + ] = None + total_matching: Annotated[ + int | None, + Field( + description='Total number of products matching the context (may be more than returned in matching_products)', + ge=0, + ), + ] = None + ttl_seconds: Annotated[ + int | None, + Field( + description='How long this offering information is valid (seconds). Host should re-fetch after TTL expires.', + ge=0, + ), + ] = None + unavailable_reason: Annotated[ + str | None, + Field( + description="If not available, why (e.g., 'expired', 'sold_out', 'region_restricted')" + ), + ] = None diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_identity.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_identity.py new file mode 100644 index 00000000..2dd21de9 --- /dev/null +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_identity.py @@ -0,0 +1,78 @@ +# generated by datamodel-codegen: +# filename: sponsored_intelligence/si_identity.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import AnyUrl, AwareDatetime, ConfigDict, EmailStr, Field + + +class ConsentScopeEnum(Enum): + name = 'name' + email = 'email' + shipping_address = 'shipping_address' + phone = 'phone' + locale = 'locale' + + +class PrivacyPolicyAcknowledged(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + brand_policy_url: Annotated[ + AnyUrl | None, Field(description="URL to brand's privacy policy") + ] = None + brand_policy_version: Annotated[ + str | None, Field(description='Version of policy acknowledged') + ] = None + + +class ShippingAddress(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + city: str | None = None + country: str | None = None + postal_code: str | None = None + state: str | None = None + street: str | None = None + + +class User(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + email: Annotated[EmailStr | None, Field(description="User's email address")] = None + locale: Annotated[str | None, Field(description="User's locale (e.g., en-US)")] = None + name: Annotated[str | None, Field(description="User's display name")] = None + phone: Annotated[str | None, Field(description="User's phone number")] = None + shipping_address: Annotated[ + ShippingAddress | None, Field(description="User's shipping address for accurate pricing") + ] = None + + +class SiIdentity(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + anonymous_session_id: Annotated[ + str | None, + Field(description='Session ID for anonymous users (when consent_granted is false)'), + ] = None + consent_granted: Annotated[bool, Field(description='Whether user consented to share identity')] + consent_scope: Annotated[ + list[ConsentScopeEnum] | None, Field(description='What data was consented to share') + ] = None + consent_timestamp: Annotated[ + AwareDatetime | None, Field(description='When consent was granted (ISO 8601)') + ] = None + privacy_policy_acknowledged: Annotated[ + PrivacyPolicyAcknowledged | None, Field(description='Brand privacy policy acknowledgment') + ] = None + user: Annotated[ + User | None, Field(description='User data (only present if consent_granted is true)') + ] = None diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_initiate_session_request.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_initiate_session_request.py new file mode 100644 index 00000000..3fee9f2f --- /dev/null +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_initiate_session_request.py @@ -0,0 +1,46 @@ +# generated by datamodel-codegen: +# filename: sponsored_intelligence/si_initiate_session_request.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field + +from ..core import ext as ext_1 +from . import si_capabilities, si_identity + + +class SiInitiateSessionRequest(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + context: Annotated[ + str, Field(description='Conversation handoff from the host describing what the user needs') + ] + ext: ext_1.ExtensionObject | None = None + identity: si_identity.SiIdentity + media_buy_id: Annotated[ + str | None, Field(description='AdCP media buy ID if session was triggered by advertising') + ] = None + offering_id: Annotated[ + str | None, Field(description='Brand-specific offering identifier to apply') + ] = None + offering_token: Annotated[ + str | None, + Field( + description="Token from si_get_offering response for session continuity. Brand uses this to recall what products were shown to the user, enabling natural references like 'the second one' or 'that blue shoe'." + ), + ] = None + placement: Annotated[ + str | None, + Field( + description="Where this session was triggered (e.g., 'chatgpt_search', 'claude_chat')" + ), + ] = None + supported_capabilities: Annotated[ + si_capabilities.SiCapabilities | None, + Field(description='What capabilities the host supports'), + ] = None diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_initiate_session_response.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_initiate_session_response.py new file mode 100644 index 00000000..1f9a2c5c --- /dev/null +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_initiate_session_response.py @@ -0,0 +1,44 @@ +# generated by datamodel-codegen: +# filename: sponsored_intelligence/si_initiate_session_response.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field + +from ..core import error +from ..core import ext as ext_1 +from . import si_capabilities, si_ui_element + + +class Response(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + message: Annotated[str | None, Field(description='Conversational message from brand agent')] = ( + None + ) + ui_elements: Annotated[ + list[si_ui_element.SiUiElement] | None, Field(description='Visual components to render') + ] = None + + +class SiInitiateSessionResponse(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + errors: Annotated[ + list[error.Error] | None, Field(description='Errors during session initiation') + ] = None + ext: ext_1.ExtensionObject | None = None + negotiated_capabilities: Annotated[ + si_capabilities.SiCapabilities | None, + Field(description='Intersection of brand and host capabilities for this session'), + ] = None + response: Annotated[Response | None, Field(description="Brand agent's initial response")] = None + session_id: Annotated[ + str, Field(description='Unique session identifier for subsequent messages') + ] diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_send_message_request.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_send_message_request.py new file mode 100644 index 00000000..4bdf9390 --- /dev/null +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_send_message_request.py @@ -0,0 +1,58 @@ +# generated by datamodel-codegen: +# filename: sponsored_intelligence/si_send_message_request.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from typing import Annotated, Any + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field, RootModel + +from ..core import ext as ext_1 + + +class ActionResponse(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + action: Annotated[str | None, Field(description='The action that was triggered')] = None + payload: Annotated[ + dict[str, Any] | None, Field(description='Action-specific response data') + ] = None + + +class SiSendMessageRequest1(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + action_response: Annotated[ + ActionResponse | None, + Field(description='Response to a previous action_button (e.g., user clicked checkout)'), + ] = None + ext: ext_1.ExtensionObject | None = None + message: Annotated[str, Field(description="User's message to the brand agent")] + session_id: Annotated[str, Field(description='Active session identifier')] + + +class SiSendMessageRequest2(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + action_response: Annotated[ + ActionResponse, + Field(description='Response to a previous action_button (e.g., user clicked checkout)'), + ] + ext: ext_1.ExtensionObject | None = None + message: Annotated[str | None, Field(description="User's message to the brand agent")] = None + session_id: Annotated[str, Field(description='Active session identifier')] + + +class SiSendMessageRequest(RootModel[SiSendMessageRequest1 | SiSendMessageRequest2]): + root: Annotated[ + SiSendMessageRequest1 | SiSendMessageRequest2, + Field( + description='Send a message to the brand agent within an active session', + title='SI Send Message Request', + ), + ] diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_send_message_response.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_send_message_response.py new file mode 100644 index 00000000..c29edf07 --- /dev/null +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_send_message_response.py @@ -0,0 +1,101 @@ +# generated by datamodel-codegen: +# filename: sponsored_intelligence/si_send_message_response.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated, Any + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field + +from ..core import error +from ..core import ext as ext_1 +from . import si_ui_element + + +class ContextForCheckout(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + applied_offers: Annotated[ + list[str] | None, Field(description='Offer IDs that were applied during the conversation') + ] = None + conversation_summary: Annotated[ + str | None, Field(description='Summary of the conversation leading to purchase') + ] = None + + +class Price(AdCPBaseModel): + amount: float | None = None + currency: str | None = None + + +class Intent(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + action: Annotated[str | None, Field(description="The commerce action (e.g., 'purchase')")] = ( + None + ) + price: Annotated[Price | None, Field(description='Price information')] = None + product: Annotated[dict[str, Any] | None, Field(description='Product details for checkout')] = ( + None + ) + + +class Type(Enum): + transaction = 'transaction' + complete = 'complete' + + +class Handoff(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + context_for_checkout: Annotated[ + ContextForCheckout | None, Field(description='Context to pass to ACP for seamless checkout') + ] = None + intent: Annotated[ + Intent | None, + Field(description='For transaction handoffs: what the user wants to purchase'), + ] = None + type: Annotated[ + Type | None, + Field( + description='Type of handoff: transaction (ready for ACP checkout) or complete (conversation done)' + ), + ] = None + + +class SessionStatus(Enum): + active = 'active' + pending_handoff = 'pending_handoff' + complete = 'complete' + + +class Response(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + message: Annotated[str | None, Field(description='Conversational message from brand agent')] = ( + None + ) + ui_elements: Annotated[ + list[si_ui_element.SiUiElement] | None, Field(description='Visual components to render') + ] = None + + +class SiSendMessageResponse(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + errors: list[error.Error] | None = None + ext: ext_1.ExtensionObject | None = None + handoff: Annotated[ + Handoff | None, Field(description='Handoff request when session_status is pending_handoff') + ] = None + response: Annotated[Response | None, Field(description="Brand agent's response")] = None + session_id: Annotated[str, Field(description='Session identifier')] + session_status: Annotated[SessionStatus, Field(description='Current session status')] diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_terminate_session_request.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_terminate_session_request.py new file mode 100644 index 00000000..a87a7700 --- /dev/null +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_terminate_session_request.py @@ -0,0 +1,60 @@ +# generated by datamodel-codegen: +# filename: sponsored_intelligence/si_terminate_session_request.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated, Any + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field + +from ..core import ext as ext_1 + + +class Reason(Enum): + handoff_transaction = 'handoff_transaction' + handoff_complete = 'handoff_complete' + user_exit = 'user_exit' + session_timeout = 'session_timeout' + host_terminated = 'host_terminated' + + +class Action(Enum): + purchase = 'purchase' + subscribe = 'subscribe' + + +class TransactionIntent(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + action: Action | None = None + product: Annotated[dict[str, Any] | None, Field(description='Product/service details')] = None + + +class TerminationContext(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + cause: Annotated[ + str | None, Field(description='For host_terminated - why host ended session') + ] = None + summary: Annotated[str | None, Field(description='Summary of the conversation')] = None + transaction_intent: Annotated[ + TransactionIntent | None, + Field(description='For handoff_transaction - what user wants to buy'), + ] = None + + +class SiTerminateSessionRequest(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + ext: ext_1.ExtensionObject | None = None + reason: Annotated[Reason, Field(description='Reason for termination')] + session_id: Annotated[str, Field(description='Session identifier to terminate')] + termination_context: Annotated[ + TerminationContext | None, Field(description='Context for the termination') + ] = None diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_terminate_session_response.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_terminate_session_response.py new file mode 100644 index 00000000..6d2d8277 --- /dev/null +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_terminate_session_response.py @@ -0,0 +1,54 @@ +# generated by datamodel-codegen: +# filename: sponsored_intelligence/si_terminate_session_response.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated, Any + +from adcp.types.base import AdCPBaseModel +from pydantic import AnyUrl, ConfigDict, Field + +from ..core import error +from ..core import ext as ext_1 + + +class AcpHandoff(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + checkout_token: Annotated[str | None, Field(description='Token for ACP checkout flow')] = None + checkout_url: Annotated[AnyUrl | None, Field(description='ACP checkout initiation URL')] = None + product: Annotated[dict[str, Any] | None, Field(description='Product details for checkout')] = ( + None + ) + + +class Action(Enum): + save_for_later = 'save_for_later' + set_reminder = 'set_reminder' + subscribe_updates = 'subscribe_updates' + none = 'none' + + +class FollowUp(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + action: Action | None = None + data: Annotated[dict[str, Any] | None, Field(description='Data for follow-up action')] = None + + +class SiTerminateSessionResponse(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + acp_handoff: Annotated[ + AcpHandoff | None, Field(description='ACP checkout handoff data (for handoff_transaction)') + ] = None + errors: list[error.Error] | None = None + ext: ext_1.ExtensionObject | None = None + follow_up: Annotated[FollowUp | None, Field(description='Suggested follow-up actions')] = None + session_id: Annotated[str, Field(description='Terminated session identifier')] + terminated: Annotated[bool, Field(description='Whether session was successfully terminated')] diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_ui_element.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_ui_element.py new file mode 100644 index 00000000..28dc97a5 --- /dev/null +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_ui_element.py @@ -0,0 +1,30 @@ +# generated by datamodel-codegen: +# filename: sponsored_intelligence/si_ui_element.json +# timestamp: 2026-01-25T21:17:54+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Annotated, Any + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field + + +class Type(Enum): + text = 'text' + link = 'link' + image = 'image' + product_card = 'product_card' + carousel = 'carousel' + action_button = 'action_button' + app_handoff = 'app_handoff' + integration_actions = 'integration_actions' + + +class SiUiElement(AdCPBaseModel): + model_config = ConfigDict( + extra='allow', + ) + data: Annotated[dict[str, Any] | None, Field(description='Component-specific data')] = None + type: Annotated[Type, Field(description='Component type')] diff --git a/src/adcp/utils/format_assets.py b/src/adcp/utils/format_assets.py index 3939686a..461f0b89 100644 --- a/src/adcp/utils/format_assets.py +++ b/src/adcp/utils/format_assets.py @@ -28,13 +28,13 @@ from typing import TYPE_CHECKING, Any, Union from adcp.types.generated_poc.core.format import Assets as AssetsModel -from adcp.types.generated_poc.core.format import Assets1 as Assets1Model +from adcp.types.generated_poc.core.format import Assets5 as Assets5Model if TYPE_CHECKING: - from adcp.types.generated_poc.core.format import Assets, Assets1, Format + from adcp.types.generated_poc.core.format import Assets, Assets5, Format # Type alias for any format asset (individual or repeatable group) -FormatAsset = Union["Assets", "Assets1"] +FormatAsset = Union["Assets", "Assets5"] def get_format_assets(format: Format) -> list[FormatAsset]: @@ -93,8 +93,8 @@ def normalize_assets_required(assets_required: list[Any]) -> list[FormatAsset]: # Check if it's a repeatable group (has asset_group_id) or individual asset if "asset_group_id" in asset_dict: - # Repeatable group - use Assets1Model - normalized.append(Assets1Model(**{**asset_dict, "required": True})) + # Repeatable group - use Assets5Model + normalized.append(Assets5Model(**{**asset_dict, "required": True})) else: # Individual asset - use AssetsModel normalized.append(AssetsModel(**{**asset_dict, "required": True})) diff --git a/tests/test_cli.py b/tests/test_cli.py index b0845e2b..962f1040 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -279,6 +279,40 @@ def test_invalid_protocol(self, tmp_path, monkeypatch): class TestCLIIntegration: """Integration tests for CLI (with mocked network calls).""" + def test_tool_dispatch_includes_all_v3_operations(self): + """Test that TOOL_DISPATCH includes all V3 protocol operations.""" + from adcp.__main__ import TOOL_DISPATCH + + # Core operations + assert "get_products" in TOOL_DISPATCH + assert "create_media_buy" in TOOL_DISPATCH + assert "list_tools" in TOOL_DISPATCH + + # V3 Protocol Discovery + assert "get_adcp_capabilities" in TOOL_DISPATCH + + # V3 Content Standards + assert "create_content_standards" in TOOL_DISPATCH + assert "get_content_standards" in TOOL_DISPATCH + assert "list_content_standards" in TOOL_DISPATCH + assert "update_content_standards" in TOOL_DISPATCH + assert "calibrate_content" in TOOL_DISPATCH + assert "validate_content_delivery" in TOOL_DISPATCH + assert "get_media_buy_artifacts" in TOOL_DISPATCH + + # V3 Sponsored Intelligence + assert "si_get_offering" in TOOL_DISPATCH + assert "si_initiate_session" in TOOL_DISPATCH + assert "si_send_message" in TOOL_DISPATCH + assert "si_terminate_session" in TOOL_DISPATCH + + # V3 Governance (Property Lists) + assert "create_property_list" in TOOL_DISPATCH + assert "get_property_list" in TOOL_DISPATCH + assert "list_property_lists" in TOOL_DISPATCH + assert "update_property_list" in TOOL_DISPATCH + assert "delete_property_list" in TOOL_DISPATCH + @pytest.mark.asyncio async def test_list_tools_dispatch(self): """Test that list_tools is in TOOL_DISPATCH and handled correctly.""" @@ -366,11 +400,14 @@ class TestDeprecatedFieldWarnings: def test_check_deprecated_fields_warns_on_assets_required(self, capsys): """Should warn when response contains deprecated assets_required field.""" - from adcp import Format, FormatCategory, FormatId + from adcp import Format, FormatCategory from adcp.__main__ import _check_deprecated_fields + # Use the core FormatId which is a proper format identifier type + from adcp.types.generated_poc.core.format_id import FormatId as CoreFormatId + fmt = Format( - format_id=FormatId(agent_url="https://test.com", id="test"), + format_id=CoreFormatId(agent_url="https://test.com", id="test"), name="Test", type=FormatCategory.display, assets_required=[ @@ -385,11 +422,14 @@ def test_check_deprecated_fields_warns_on_assets_required(self, capsys): def test_check_deprecated_fields_no_warning_for_new_assets(self, capsys): """Should not warn when using new assets field.""" - from adcp import Format, FormatCategory, FormatId + from adcp import Format, FormatCategory from adcp.__main__ import _check_deprecated_fields + # Use the core FormatId which is a proper format identifier type + from adcp.types.generated_poc.core.format_id import FormatId as CoreFormatId + fmt = Format( - format_id=FormatId(agent_url="https://test.com", id="test"), + format_id=CoreFormatId(agent_url="https://test.com", id="test"), name="Test", type=FormatCategory.display, assets=[ diff --git a/tests/test_server_framework.py b/tests/test_server_framework.py new file mode 100644 index 00000000..8f3ec645 --- /dev/null +++ b/tests/test_server_framework.py @@ -0,0 +1,532 @@ +"""Tests for ADCP server framework.""" + +import pytest + +from adcp.server import ( + ADCPHandler, + ContentStandardsHandler, + GovernanceHandler, + MCPToolSet, + NotImplementedResponse, + ProposalBuilder, + ProposalNotSupported, + SponsoredIntelligenceHandler, + ToolContext, + create_mcp_tools, + not_supported, +) +from adcp.server.proposal import proposals_not_supported +from adcp.types import ( + CalibrateContentRequest, + CalibrateContentResponse, + CreateContentStandardsRequest, + CreateContentStandardsResponse, + CreatePropertyListResponse, + DeletePropertyListResponse, + GetContentStandardsRequest, + GetContentStandardsResponse, + GetMediaBuyArtifactsRequest, + GetMediaBuyArtifactsResponse, + GetPropertyListResponse, + ListContentStandardsRequest, + ListContentStandardsResponse, + ListPropertyListsResponse, + SiGetOfferingRequest, + SiGetOfferingResponse, + SiInitiateSessionRequest, + SiInitiateSessionResponse, + SiSendMessageRequest, + SiSendMessageResponse, + SiTerminateSessionRequest, + SiTerminateSessionResponse, + UpdateContentStandardsRequest, + UpdateContentStandardsResponse, + UpdatePropertyListResponse, + ValidateContentDeliveryRequest, + ValidateContentDeliveryResponse, +) + + +class TestNotSupported: + """Tests for not_supported helper.""" + + def test_not_supported_default_message(self): + """Test not_supported with default message.""" + response = not_supported() + assert response.supported is False + assert response.error is not None + assert response.error.code == "NOT_SUPPORTED" + + def test_not_supported_custom_message(self): + """Test not_supported with custom message.""" + response = not_supported("Custom reason here") + assert response.supported is False + assert response.reason == "Custom reason here" + assert response.error.message == "Custom reason here" + + +class TestToolContext: + """Tests for ToolContext.""" + + def test_tool_context_defaults(self): + """Test ToolContext has sensible defaults.""" + ctx = ToolContext() + assert ctx.request_id is None + assert ctx.caller_identity is None + assert ctx.metadata == {} + + def test_tool_context_with_values(self): + """Test ToolContext with values.""" + ctx = ToolContext( + request_id="req-123", + caller_identity="agent@example.com", + metadata={"key": "value"}, + ) + assert ctx.request_id == "req-123" + assert ctx.caller_identity == "agent@example.com" + assert ctx.metadata["key"] == "value" + + +class TestADCPHandler: + """Tests for base ADCPHandler.""" + + @pytest.mark.asyncio + async def test_default_get_products_returns_not_supported(self): + """Test default get_products returns not supported.""" + handler = ADCPHandler() + result = await handler.get_products({}) + assert isinstance(result, NotImplementedResponse) + assert result.supported is False + assert "get_products" in result.reason + + @pytest.mark.asyncio + async def test_default_create_media_buy_returns_not_supported(self): + """Test default create_media_buy returns not supported.""" + handler = ADCPHandler() + result = await handler.create_media_buy({}) + assert isinstance(result, NotImplementedResponse) + assert result.supported is False + + @pytest.mark.asyncio + async def test_default_content_standards_returns_not_supported(self): + """Test default content standards methods return not supported.""" + handler = ADCPHandler() + + result = await handler.create_content_standards({}) + assert isinstance(result, NotImplementedResponse) + + result = await handler.calibrate_content({}) + assert isinstance(result, NotImplementedResponse) + + @pytest.mark.asyncio + async def test_default_si_methods_return_not_supported(self): + """Test default sponsored intelligence methods return not supported.""" + handler = ADCPHandler() + + result = await handler.si_get_offering({}) + assert isinstance(result, NotImplementedResponse) + + result = await handler.si_initiate_session({}) + assert isinstance(result, NotImplementedResponse) + + +class TestContentStandardsHandler: + """Tests for ContentStandardsHandler.""" + + def create_concrete_handler(self): + """Create a concrete handler for testing.""" + + class ConcreteCSHandler(ContentStandardsHandler): + async def create_content_standards(self, request, context=None): + return CreateContentStandardsResponse() + + async def get_content_standards(self, request, context=None): + return GetContentStandardsResponse() + + async def list_content_standards(self, request, context=None): + return ListContentStandardsResponse() + + async def update_content_standards(self, request, context=None): + return UpdateContentStandardsResponse() + + async def calibrate_content(self, request, context=None): + return CalibrateContentResponse() + + async def validate_content_delivery(self, request, context=None): + return ValidateContentDeliveryResponse() + + async def get_media_buy_artifacts(self, request, context=None): + return GetMediaBuyArtifactsResponse() + + return ConcreteCSHandler() + + @pytest.mark.asyncio + async def test_get_products_returns_not_supported(self): + """Test get_products is stubbed as not supported.""" + handler = self.create_concrete_handler() + result = await handler.get_products({}) + assert isinstance(result, NotImplementedResponse) + assert result.supported is False + assert "Content Standards" in result.reason + + @pytest.mark.asyncio + async def test_create_media_buy_returns_not_supported(self): + """Test create_media_buy is stubbed as not supported.""" + handler = self.create_concrete_handler() + result = await handler.create_media_buy({}) + assert isinstance(result, NotImplementedResponse) + assert "media buying" in result.reason.lower() or "Content Standards" in result.reason + + @pytest.mark.asyncio + async def test_si_methods_return_not_supported(self): + """Test SI methods are stubbed as not supported.""" + handler = self.create_concrete_handler() + + result = await handler.si_get_offering({}) + assert isinstance(result, NotImplementedResponse) + assert "Sponsored Intelligence" in result.reason + + @pytest.mark.asyncio + async def test_signal_methods_return_not_supported(self): + """Test signal methods are stubbed as not supported.""" + handler = self.create_concrete_handler() + + result = await handler.get_signals({}) + assert isinstance(result, NotImplementedResponse) + + result = await handler.activate_signal({}) + assert isinstance(result, NotImplementedResponse) + + @pytest.mark.asyncio + async def test_governance_methods_return_not_supported(self): + """Test governance methods are stubbed as not supported.""" + handler = self.create_concrete_handler() + + result = await handler.create_property_list({}) + assert isinstance(result, NotImplementedResponse) + assert "Governance" in result.reason + + result = await handler.list_property_lists({}) + assert isinstance(result, NotImplementedResponse) + + +class TestSponsoredIntelligenceHandler: + """Tests for SponsoredIntelligenceHandler.""" + + def create_concrete_handler(self): + """Create a concrete handler for testing.""" + + class ConcreteSIHandler(SponsoredIntelligenceHandler): + async def si_get_offering(self, request, context=None): + return SiGetOfferingResponse() + + async def si_initiate_session(self, request, context=None): + return SiInitiateSessionResponse() + + async def si_send_message(self, request, context=None): + return SiSendMessageResponse() + + async def si_terminate_session(self, request, context=None): + return SiTerminateSessionResponse() + + return ConcreteSIHandler() + + @pytest.mark.asyncio + async def test_get_products_returns_not_supported(self): + """Test get_products is stubbed as not supported.""" + handler = self.create_concrete_handler() + result = await handler.get_products({}) + assert isinstance(result, NotImplementedResponse) + assert result.supported is False + assert "Sponsored Intelligence" in result.reason + + @pytest.mark.asyncio + async def test_create_media_buy_returns_not_supported(self): + """Test create_media_buy is stubbed as not supported.""" + handler = self.create_concrete_handler() + result = await handler.create_media_buy({}) + assert isinstance(result, NotImplementedResponse) + assert "si_initiate_session" in result.reason.lower() or "Sponsored Intelligence" in result.reason + + @pytest.mark.asyncio + async def test_content_standards_returns_not_supported(self): + """Test content standards methods are stubbed as not supported.""" + handler = self.create_concrete_handler() + + result = await handler.create_content_standards({}) + assert isinstance(result, NotImplementedResponse) + assert "Content Standards" in result.reason + + result = await handler.calibrate_content({}) + assert isinstance(result, NotImplementedResponse) + + @pytest.mark.asyncio + async def test_governance_methods_return_not_supported(self): + """Test governance methods are stubbed as not supported.""" + handler = self.create_concrete_handler() + + result = await handler.create_property_list({}) + assert isinstance(result, NotImplementedResponse) + assert "Governance" in result.reason + + result = await handler.list_property_lists({}) + assert isinstance(result, NotImplementedResponse) + + +class TestGovernanceHandler: + """Tests for GovernanceHandler.""" + + def create_concrete_handler(self): + """Create a concrete handler for testing.""" + + class ConcreteGovHandler(GovernanceHandler): + async def create_property_list(self, request, context=None): + return CreatePropertyListResponse() + + async def get_property_list(self, request, context=None): + return GetPropertyListResponse() + + async def list_property_lists(self, request, context=None): + return ListPropertyListsResponse(lists=[]) + + async def update_property_list(self, request, context=None): + return UpdatePropertyListResponse() + + async def delete_property_list(self, request, context=None): + return DeletePropertyListResponse() + + return ConcreteGovHandler() + + @pytest.mark.asyncio + async def test_get_products_returns_not_supported(self): + """Test get_products is stubbed as not supported.""" + handler = self.create_concrete_handler() + result = await handler.get_products({}) + assert isinstance(result, NotImplementedResponse) + assert result.supported is False + assert "Governance" in result.reason + + @pytest.mark.asyncio + async def test_create_media_buy_returns_not_supported(self): + """Test create_media_buy is stubbed as not supported.""" + handler = self.create_concrete_handler() + result = await handler.create_media_buy({}) + assert isinstance(result, NotImplementedResponse) + assert "Governance" in result.reason + + @pytest.mark.asyncio + async def test_content_standards_returns_not_supported(self): + """Test content standards methods are stubbed as not supported.""" + handler = self.create_concrete_handler() + + result = await handler.create_content_standards({}) + assert isinstance(result, NotImplementedResponse) + assert "Content Standards" in result.reason + + result = await handler.calibrate_content({}) + assert isinstance(result, NotImplementedResponse) + + @pytest.mark.asyncio + async def test_si_methods_return_not_supported(self): + """Test SI methods are stubbed as not supported.""" + handler = self.create_concrete_handler() + + result = await handler.si_get_offering({}) + assert isinstance(result, NotImplementedResponse) + assert "Sponsored Intelligence" in result.reason + + @pytest.mark.asyncio + async def test_list_authorized_properties_suggests_alternative(self): + """Test list_authorized_properties suggests using get_property_list.""" + handler = self.create_concrete_handler() + result = await handler.list_authorized_properties({}) + assert isinstance(result, NotImplementedResponse) + assert "get_property_list" in result.reason + + +class TestProposalBuilder: + """Tests for ProposalBuilder.""" + + def test_build_simple_proposal(self): + """Test building a simple proposal.""" + proposal = ( + ProposalBuilder("Test Campaign") + .add_allocation("product-1", 100) + .build() + ) + + assert proposal["name"] == "Test Campaign" + assert "proposal_id" in proposal + assert len(proposal["allocations"]) == 1 + assert proposal["allocations"][0]["product_id"] == "product-1" + assert proposal["allocations"][0]["allocation_percentage"] == 100 + + def test_build_multi_allocation_proposal(self): + """Test building a proposal with multiple allocations.""" + proposal = ( + ProposalBuilder("Multi Product Campaign") + .with_description("A balanced approach") + .add_allocation("product-1", 60) + .with_rationale("High-impact display") + .add_allocation("product-2", 40) + .with_rationale("Contextual targeting") + .build() + ) + + assert proposal["name"] == "Multi Product Campaign" + assert proposal["description"] == "A balanced approach" + assert len(proposal["allocations"]) == 2 + assert proposal["allocations"][0]["allocation_percentage"] == 60 + assert proposal["allocations"][0]["rationale"] == "High-impact display" + assert proposal["allocations"][1]["allocation_percentage"] == 40 + + def test_build_proposal_with_budget_guidance(self): + """Test building proposal with budget guidance.""" + proposal = ( + ProposalBuilder("Budget Campaign") + .add_allocation("product-1", 100) + .with_budget_guidance(min=5000, recommended=10000, max=20000) + .build() + ) + + assert "total_budget_guidance" in proposal + guidance = proposal["total_budget_guidance"] + assert guidance["min"] == 5000 + assert guidance["recommended"] == 10000 + assert guidance["max"] == 20000 + assert guidance["currency"] == "USD" + + def test_build_proposal_with_custom_id(self): + """Test building proposal with custom ID.""" + proposal = ( + ProposalBuilder("Custom ID Campaign", proposal_id="my-custom-id") + .add_allocation("product-1", 100) + .build() + ) + + assert proposal["proposal_id"] == "my-custom-id" + + def test_allocation_validation_fails_if_not_100(self): + """Test that allocations must sum to 100.""" + with pytest.raises(ValueError, match="sum to 100"): + ProposalBuilder("Bad Campaign").add_allocation("product-1", 50).build() + + def test_allocation_validation_empty_allocations(self): + """Test that at least one allocation is required.""" + with pytest.raises(ValueError, match="at least one allocation"): + ProposalBuilder("Empty Campaign").build() + + def test_validate_without_building(self): + """Test validate method returns errors without raising.""" + builder = ProposalBuilder("Incomplete Campaign").add_allocation("product-1", 50) + errors = builder.validate() + assert len(errors) == 1 + assert "sum to 100" in errors[0] + + def test_validate_valid_proposal(self): + """Test validate returns empty for valid proposal.""" + builder = ProposalBuilder("Valid Campaign").add_allocation("product-1", 100) + errors = builder.validate() + assert errors == [] + + +class TestProposalNotSupported: + """Tests for ProposalNotSupported.""" + + def test_proposals_not_supported_helper(self): + """Test proposals_not_supported helper.""" + response = proposals_not_supported("Custom reason") + assert isinstance(response, ProposalNotSupported) + assert response.proposals_supported is False + assert response.reason == "Custom reason" + assert response.error.code == "PROPOSALS_NOT_SUPPORTED" + + +class TestMCPToolSet: + """Tests for MCPToolSet and create_mcp_tools.""" + + def test_create_mcp_tools(self): + """Test creating MCP tools from a handler.""" + handler = ADCPHandler() + tools = create_mcp_tools(handler) + + assert isinstance(tools, MCPToolSet) + assert len(tools.tool_definitions) > 0 + + def test_tool_definitions_have_required_fields(self): + """Test tool definitions have name, description, inputSchema.""" + handler = ADCPHandler() + tools = create_mcp_tools(handler) + + for tool_def in tools.tool_definitions: + assert "name" in tool_def + assert "description" in tool_def + assert "inputSchema" in tool_def + + def test_get_tool_names(self): + """Test getting list of tool names.""" + handler = ADCPHandler() + tools = create_mcp_tools(handler) + names = tools.get_tool_names() + + # Should include core ADCP operations + assert "get_products" in names + assert "create_media_buy" in names + assert "get_adcp_capabilities" in names + + # Should include V3 Content Standards + assert "create_content_standards" in names + assert "calibrate_content" in names + + # Should include V3 Sponsored Intelligence + assert "si_get_offering" in names + assert "si_send_message" in names + + @pytest.mark.asyncio + async def test_call_tool_invokes_handler(self): + """Test calling a tool invokes the handler method.""" + handler = ADCPHandler() + tools = create_mcp_tools(handler) + + result = await tools.call_tool("get_products", {}) + + # Should return the not_supported response as a dict + assert result["supported"] is False + + @pytest.mark.asyncio + async def test_call_unknown_tool_raises(self): + """Test calling unknown tool raises KeyError.""" + handler = ADCPHandler() + tools = create_mcp_tools(handler) + + with pytest.raises(KeyError, match="Unknown tool"): + await tools.call_tool("nonexistent_tool", {}) + + +class TestServerModuleExports: + """Test that server module exports are correct.""" + + def test_all_exports_available(self): + """Test all expected exports are available from adcp.server.""" + from adcp.server import ( + ADCPHandler, + ContentStandardsHandler, + NotImplementedResponse, + ProposalBuilder, + ProposalNotSupported, + SponsoredIntelligenceHandler, + ToolContext, + create_mcp_tools, + not_supported, + ) + + # Just verify they're importable and are the right types + assert ADCPHandler is not None + assert ContentStandardsHandler is not None + assert SponsoredIntelligenceHandler is not None + assert ProposalBuilder is not None + assert ProposalNotSupported is not None + assert NotImplementedResponse is not None + assert ToolContext is not None + assert create_mcp_tools is not None + assert not_supported is not None diff --git a/tests/test_type_aliases.py b/tests/test_type_aliases.py index bce5c125..f57fe21b 100644 --- a/tests/test_type_aliases.py +++ b/tests/test_type_aliases.py @@ -158,17 +158,21 @@ def test_all_request_aliases_exported(): def test_all_activation_key_aliases_exported(): - """Test that all activation key aliases are exported.""" - expected_aliases = [ - "PropertyIdActivationKey", - "PropertyTagActivationKey", - ] + """Test that activation key types are available. - import adcp.types.aliases as aliases_module + Note: The activation key schema changed in the latest ADCP schemas. + Previously it had property_id/property_tag variants (PropertyIdActivationKey, + PropertyTagActivationKey). Now it uses segment_id/key_value variants. + Direct activation key types are available from the generated types. + """ + # Activation key types are now segment_id and key_value based + # Import directly from generated types, not aliases + from adcp.types._generated import ActivationKey, ActivationKey1, ActivationKey2 - for alias in expected_aliases: - assert hasattr(aliases_module, alias), f"Missing alias: {alias}" - assert alias in aliases_module.__all__, f"Alias not in __all__: {alias}" + # Basic sanity check that the types exist + assert ActivationKey is not None + assert ActivationKey1 is not None # segment_id variant + assert ActivationKey2 is not None # key_value variant def test_all_preview_render_aliases_exported(): @@ -428,32 +432,33 @@ def test_publisher_properties_aliases_in_exports(): def test_property_id_and_tag_are_root_models(): - """Test that PropertyId and PropertyTag are properly constrained string types. + """Test that core PropertyId and PropertyTag are properly constrained string types. - As of AdCP v1.0.0, PropertyId and PropertyTag are separate RootModel types - defined in their own schema files, not in an inheritance relationship. - Both use the same pattern constraint (^[a-z0-9_]+$) but are semantically distinct. + Note: PropertyId is defined in both core/property_id.json and content_standards/artifact.json + with different structures. The core PropertyId is a RootModel[str] while the artifact + PropertyId is an object type. This test verifies the core types from their original modules. """ from pydantic import RootModel - from adcp import PropertyId, PropertyTag + # Import directly from the core modules to avoid collision + from adcp.types.generated_poc.core.property_id import PropertyId as CorePropertyId + from adcp.types.generated_poc.core.property_tag import PropertyTag # Create valid PropertyId and PropertyTag - prop_id = PropertyId("my_property_id") - prop_tag = PropertyTag("premium") + prop_id = CorePropertyId(root="my_property_id") + prop_tag = PropertyTag(root="premium") # Verify they are created successfully assert prop_id.root == "my_property_id" assert prop_tag.root == "premium" # Both should be RootModel subclasses (but not related to each other) - assert issubclass(PropertyId, RootModel) + assert issubclass(CorePropertyId, RootModel) assert issubclass(PropertyTag, RootModel) # They are separate types, not in an inheritance relationship - assert PropertyId is not PropertyTag - assert not issubclass(PropertyTag, PropertyId) - assert not issubclass(PropertyId, PropertyTag) + assert CorePropertyId is not PropertyTag + assert not issubclass(PropertyTag, CorePropertyId) def test_deployment_aliases_imports(): diff --git a/tests/test_type_coercion.py b/tests/test_type_coercion.py index 09755e74..20784b84 100644 --- a/tests/test_type_coercion.py +++ b/tests/test_type_coercion.py @@ -134,7 +134,7 @@ def test_fields_accepts_string_list(self): assert len(req.fields) == 3 assert req.fields[0] == FieldModel.creative_id assert req.fields[1] == FieldModel.name - assert req.fields[2] == FieldModel.format + assert req.fields[2] == FieldModel.format_ # format_ to avoid Python keyword collision assert all(isinstance(x, FieldModel) for x in req.fields) def test_fields_accepts_enum_list(self): @@ -332,11 +332,11 @@ class ExtendedPackage(PackageRequest): assert request.packages[0].campaign_id == "internal-campaign-456" # type: ignore[attr-defined] def test_update_packages_accepts_extended_creatives(self): - """UpdateMediaBuyRequest Packages types accept extended CreativeAsset.""" + """UpdateMediaBuyRequest PackageUpdate types accept extended CreativeAsset.""" from pydantic import Field from adcp.types import CreativeAsset, FormatId - from adcp.types.generated_poc.media_buy.update_media_buy_request import Packages + from adcp.types.generated_poc.media_buy.package_update import PackageUpdate1 class ExtendedCreative(CreativeAsset): internal_id: str | None = Field(None, exclude=True) @@ -350,13 +350,13 @@ class ExtendedCreative(CreativeAsset): ) # No cast() needed! - packages = Packages( + package_update = PackageUpdate1( package_id="pkg1", creatives=[creative], # type: ignore[list-item] ) - assert len(packages.creatives) == 1 - assert packages.creatives[0].creative_id == "c1" + assert len(package_update.creatives) == 1 + assert package_update.creatives[0].creative_id == "c1" class TestSerializationRoundtrip: @@ -590,9 +590,12 @@ def test_response_errors_accepts_error_subclass(self): """Response types with errors field accept Error subclass instances.""" from pydantic import Field - from adcp.types import Error, GetProductsResponse + from adcp.types import GetProductsResponse + # Import Error from core.error - the type used in ergonomic coercion + # (adcp.types.Error exports a different Error from content_standards) + from adcp.types.generated_poc.core.error import Error as CoreError - class ExtendedError(Error): + class ExtendedError(CoreError): """Extended with internal tracking fields.""" internal_trace_id: str | None = Field(None, exclude=True) From 0e86feb87c8646bb8c0348cef2b3dfdea6281800 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Mon, 26 Jan 2026 06:26:12 -0500 Subject: [PATCH 02/13] fix: resolve ruff linting errors - Fix import block sorting (I001) across multiple files - Remove unused import ContentStandards from content_standards.py - Update Callable import to collections.abc in mcp_tools.py - Fix line length (E501) in server/base.py Co-Authored-By: Claude Opus 4.5 --- src/adcp/client.py | 112 +++++++++++++-------------- src/adcp/server/base.py | 4 +- src/adcp/server/content_standards.py | 1 - src/adcp/server/mcp_tools.py | 3 +- src/adcp/types/__init__.py | 106 +++++++++++-------------- src/adcp/types/_ergonomic.py | 29 ++++--- 6 files changed, 122 insertions(+), 133 deletions(-) diff --git a/src/adcp/client.py b/src/adcp/client.py index 9449edb0..9e33ef73 100644 --- a/src/adcp/client.py +++ b/src/adcp/client.py @@ -47,13 +47,19 @@ UpdateMediaBuyRequest, UpdateMediaBuyResponse, ) - -# V3 Protocol Discovery types -from adcp.types.generated_poc.protocol.get_adcp_capabilities_request import ( - GetAdcpCapabilitiesRequest, +from adcp.types.core import ( + Activity, + ActivityType, + AgentConfig, + Protocol, + TaskResult, + TaskStatus, ) -from adcp.types.generated_poc.protocol.get_adcp_capabilities_response import ( - GetAdcpCapabilitiesResponse, +from adcp.types.generated_poc.content_standards.calibrate_content_request import ( + CalibrateContentRequest, +) +from adcp.types.generated_poc.content_standards.calibrate_content_response import ( + CalibrateContentResponse, ) # V3 Content Standards types @@ -69,6 +75,12 @@ from adcp.types.generated_poc.content_standards.get_content_standards_response import ( GetContentStandardsResponse, ) +from adcp.types.generated_poc.content_standards.get_media_buy_artifacts_request import ( + GetMediaBuyArtifactsRequest, +) +from adcp.types.generated_poc.content_standards.get_media_buy_artifacts_response import ( + GetMediaBuyArtifactsResponse, +) from adcp.types.generated_poc.content_standards.list_content_standards_request import ( ListContentStandardsRequest, ) @@ -81,50 +93,13 @@ from adcp.types.generated_poc.content_standards.update_content_standards_response import ( UpdateContentStandardsResponse, ) -from adcp.types.generated_poc.content_standards.calibrate_content_request import ( - CalibrateContentRequest, -) -from adcp.types.generated_poc.content_standards.calibrate_content_response import ( - CalibrateContentResponse, -) from adcp.types.generated_poc.content_standards.validate_content_delivery_request import ( ValidateContentDeliveryRequest, ) from adcp.types.generated_poc.content_standards.validate_content_delivery_response import ( ValidateContentDeliveryResponse, ) -from adcp.types.generated_poc.content_standards.get_media_buy_artifacts_request import ( - GetMediaBuyArtifactsRequest, -) -from adcp.types.generated_poc.content_standards.get_media_buy_artifacts_response import ( - GetMediaBuyArtifactsResponse, -) - -# V3 Sponsored Intelligence types -from adcp.types.generated_poc.sponsored_intelligence.si_get_offering_request import ( - SiGetOfferingRequest, -) -from adcp.types.generated_poc.sponsored_intelligence.si_get_offering_response import ( - SiGetOfferingResponse, -) -from adcp.types.generated_poc.sponsored_intelligence.si_initiate_session_request import ( - SiInitiateSessionRequest, -) -from adcp.types.generated_poc.sponsored_intelligence.si_initiate_session_response import ( - SiInitiateSessionResponse, -) -from adcp.types.generated_poc.sponsored_intelligence.si_send_message_request import ( - SiSendMessageRequest, -) -from adcp.types.generated_poc.sponsored_intelligence.si_send_message_response import ( - SiSendMessageResponse, -) -from adcp.types.generated_poc.sponsored_intelligence.si_terminate_session_request import ( - SiTerminateSessionRequest, -) -from adcp.types.generated_poc.sponsored_intelligence.si_terminate_session_response import ( - SiTerminateSessionResponse, -) +from adcp.types.generated_poc.core.async_response_data import AdcpAsyncResponseData # V3 Governance (Property Lists) types from adcp.types.generated_poc.property.create_property_list_request import ( @@ -133,6 +108,12 @@ from adcp.types.generated_poc.property.create_property_list_response import ( CreatePropertyListResponse, ) +from adcp.types.generated_poc.property.delete_property_list_request import ( + DeletePropertyListRequest, +) +from adcp.types.generated_poc.property.delete_property_list_response import ( + DeletePropertyListResponse, +) from adcp.types.generated_poc.property.get_property_list_request import ( GetPropertyListRequest, ) @@ -151,21 +132,40 @@ from adcp.types.generated_poc.property.update_property_list_response import ( UpdatePropertyListResponse, ) -from adcp.types.generated_poc.property.delete_property_list_request import ( - DeletePropertyListRequest, + +# V3 Protocol Discovery types +from adcp.types.generated_poc.protocol.get_adcp_capabilities_request import ( + GetAdcpCapabilitiesRequest, ) -from adcp.types.generated_poc.property.delete_property_list_response import ( - DeletePropertyListResponse, +from adcp.types.generated_poc.protocol.get_adcp_capabilities_response import ( + GetAdcpCapabilitiesResponse, ) -from adcp.types.core import ( - Activity, - ActivityType, - AgentConfig, - Protocol, - TaskResult, - TaskStatus, + +# V3 Sponsored Intelligence types +from adcp.types.generated_poc.sponsored_intelligence.si_get_offering_request import ( + SiGetOfferingRequest, +) +from adcp.types.generated_poc.sponsored_intelligence.si_get_offering_response import ( + SiGetOfferingResponse, +) +from adcp.types.generated_poc.sponsored_intelligence.si_initiate_session_request import ( + SiInitiateSessionRequest, +) +from adcp.types.generated_poc.sponsored_intelligence.si_initiate_session_response import ( + SiInitiateSessionResponse, +) +from adcp.types.generated_poc.sponsored_intelligence.si_send_message_request import ( + SiSendMessageRequest, +) +from adcp.types.generated_poc.sponsored_intelligence.si_send_message_response import ( + SiSendMessageResponse, +) +from adcp.types.generated_poc.sponsored_intelligence.si_terminate_session_request import ( + SiTerminateSessionRequest, +) +from adcp.types.generated_poc.sponsored_intelligence.si_terminate_session_response import ( + SiTerminateSessionResponse, ) -from adcp.types.generated_poc.core.async_response_data import AdcpAsyncResponseData from adcp.utils.operation_id import create_operation_id logger = logging.getLogger(__name__) diff --git a/src/adcp/server/base.py b/src/adcp/server/base.py index 26fd0e30..c827cf87 100644 --- a/src/adcp/server/base.py +++ b/src/adcp/server/base.py @@ -35,7 +35,9 @@ class NotImplementedResponse(BaseModel): error: Error | None = None -def not_supported(reason: str = "This operation is not supported by this agent") -> NotImplementedResponse: +def not_supported( + reason: str = "This operation is not supported by this agent", +) -> NotImplementedResponse: """Create a standard 'not supported' response. Use this to return from operations that your agent does not implement. diff --git a/src/adcp/server/content_standards.py b/src/adcp/server/content_standards.py index af7469ea..7c3fc848 100644 --- a/src/adcp/server/content_standards.py +++ b/src/adcp/server/content_standards.py @@ -13,7 +13,6 @@ from adcp.types import ( CalibrateContentRequest, CalibrateContentResponse, - ContentStandards, CreateContentStandardsRequest, CreateContentStandardsResponse, GetContentStandardsRequest, diff --git a/src/adcp/server/mcp_tools.py b/src/adcp/server/mcp_tools.py index 52523764..4889dc8e 100644 --- a/src/adcp/server/mcp_tools.py +++ b/src/adcp/server/mcp_tools.py @@ -5,7 +5,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Callable +from collections.abc import Callable +from typing import TYPE_CHECKING, Any from adcp.server.base import ADCPHandler, ToolContext diff --git a/src/adcp/types/__init__.py b/src/adcp/types/__init__.py index cbafe9b0..de330806 100644 --- a/src/adcp/types/__init__.py +++ b/src/adcp/types/__init__.py @@ -35,10 +35,15 @@ from adcp.types import _generated as generated # noqa: F401 # Import all types from generated code +# V3 Protocol Discovery types +# V3 Content Standards types +# V3 Sponsored Intelligence types +# V3 Governance (Property Lists) types from adcp.types._generated import ( ActivateSignalRequest, ActivateSignalResponse, AggregatedTotals, + Artifact, Asset, AssetContentType, AssetSelectors, @@ -55,9 +60,12 @@ BuildCreativeRequest, BuildCreativeResponse, ByPackageItem, + CalibrateContentRequest, + CalibrateContentResponse, CoBrandingRequirement, Colors, Contact, + ContentStandards, Country, CpcPricingOption, CpcvPricingOption, @@ -65,8 +73,12 @@ CpmFixedRatePricingOption, CppPricingOption, CpvPricingOption, + CreateContentStandardsRequest, + CreateContentStandardsResponse, CreateMediaBuyRequest, CreateMediaBuyResponse, + CreatePropertyListRequest, + CreatePropertyListResponse, Creative, CreativeAction, CreativeAgent, @@ -81,6 +93,8 @@ DaastTrackingEvent, DaastVersion, DailyBreakdownItem, + DeletePropertyListRequest, + DeletePropertyListResponse, DeliverTo, DeliveryMeasurement, DeliveryMetrics, @@ -107,10 +121,18 @@ GeoMetro, GeoPostalArea, GeoRegion, + GetAdcpCapabilitiesRequest, + GetAdcpCapabilitiesResponse, + GetContentStandardsRequest, + GetContentStandardsResponse, + GetMediaBuyArtifactsRequest, + GetMediaBuyArtifactsResponse, GetMediaBuyDeliveryRequest, GetMediaBuyDeliveryResponse, GetProductsRequest, GetProductsResponse, + GetPropertyListRequest, + GetPropertyListResponse, GetSignalsRequest, GetSignalsResponse, HtmlAsset, @@ -123,10 +145,14 @@ LandingPageRequirement, ListAuthorizedPropertiesRequest, ListAuthorizedPropertiesResponse, + ListContentStandardsRequest, + ListContentStandardsResponse, ListCreativeFormatsRequest, ListCreativeFormatsResponse, ListCreativesRequest, ListCreativesResponse, + ListPropertyListsRequest, + ListPropertyListsResponse, Logo, MarkdownFlavor, Measurement, @@ -164,6 +190,10 @@ PromotedProducts, Property, PropertyIdentifierTypes, + PropertyList, + PropertyListChangedWebhook, + PropertyListFilters, + PropertyListReference, PropertyType, ProtocolEnvelope, ProtocolResponse, @@ -183,9 +213,20 @@ Responsive, Results, Security, + SiCapabilities, + SiGetOfferingRequest, + SiGetOfferingResponse, Signal, SignalCatalogType, SignalFilters, + SiIdentity, + SiInitiateSessionRequest, + SiInitiateSessionResponse, + SiSendMessageRequest, + SiSendMessageResponse, + SiTerminateSessionRequest, + SiTerminateSessionResponse, + SiUiElement, Sort, SortApplied, SortDirection, @@ -198,11 +239,17 @@ TaskType, TextAsset, Totals, + UpdateContentStandardsRequest, + UpdateContentStandardsResponse, UpdateFrequency, UpdateMediaBuyRequest, UpdateMediaBuyResponse, + UpdatePropertyListRequest, + UpdatePropertyListResponse, UrlAsset, UrlAssetType, + ValidateContentDeliveryRequest, + ValidateContentDeliveryResponse, ValidationMode, VastTrackingEvent, VastVersion, @@ -217,65 +264,6 @@ from adcp.types._generated import TaskStatus as GeneratedTaskStatus from adcp.types._generated import _PackageFromPackage as Package -# V3 Protocol Discovery types -from adcp.types._generated import ( - GetAdcpCapabilitiesRequest, - GetAdcpCapabilitiesResponse, -) - -# V3 Content Standards types -from adcp.types._generated import ( - Artifact, - CalibrateContentRequest, - CalibrateContentResponse, - ContentStandards, - CreateContentStandardsRequest, - CreateContentStandardsResponse, - GetContentStandardsRequest, - GetContentStandardsResponse, - GetMediaBuyArtifactsRequest, - GetMediaBuyArtifactsResponse, - ListContentStandardsRequest, - ListContentStandardsResponse, - UpdateContentStandardsRequest, - UpdateContentStandardsResponse, - ValidateContentDeliveryRequest, - ValidateContentDeliveryResponse, -) - -# V3 Sponsored Intelligence types -from adcp.types._generated import ( - SiCapabilities, - SiGetOfferingRequest, - SiGetOfferingResponse, - SiIdentity, - SiInitiateSessionRequest, - SiInitiateSessionResponse, - SiSendMessageRequest, - SiSendMessageResponse, - SiTerminateSessionRequest, - SiTerminateSessionResponse, - SiUiElement, -) - -# V3 Governance (Property Lists) types -from adcp.types._generated import ( - CreatePropertyListRequest, - CreatePropertyListResponse, - DeletePropertyListRequest, - DeletePropertyListResponse, - GetPropertyListRequest, - GetPropertyListResponse, - ListPropertyListsRequest, - ListPropertyListsResponse, - PropertyList, - PropertyListChangedWebhook, - PropertyListFilters, - PropertyListReference, - UpdatePropertyListRequest, - UpdatePropertyListResponse, -) - # Import semantic aliases for discriminated unions from adcp.types.aliases import ( ActivateSignalErrorResponse, diff --git a/src/adcp/types/_ergonomic.py b/src/adcp/types/_ergonomic.py index 70a487f8..08cb1cdd 100644 --- a/src/adcp/types/_ergonomic.py +++ b/src/adcp/types/_ergonomic.py @@ -39,7 +39,6 @@ coerce_to_enum_list, coerce_to_model, ) - from adcp.types.generated_poc.core.context import ContextObject from adcp.types.generated_poc.core.creative_asset import CreativeAsset from adcp.types.generated_poc.core.creative_assignment import CreativeAssignment @@ -56,20 +55,6 @@ from adcp.types.generated_poc.media_buy.create_media_buy_request import ( CreateMediaBuyRequest, ) -from adcp.types.generated_poc.media_buy.get_products_request import GetProductsRequest -from adcp.types.generated_poc.media_buy.list_creative_formats_request import ( - ListCreativeFormatsRequest, -) -from adcp.types.generated_poc.media_buy.list_creatives_request import ( - FieldModel, - ListCreativesRequest, - Sort, -) -from adcp.types.generated_poc.media_buy.package_request import PackageRequest -from adcp.types.generated_poc.media_buy.package_update import ( - PackageUpdate1, - PackageUpdate2, -) from adcp.types.generated_poc.media_buy.create_media_buy_response import ( CreateMediaBuyResponse1, ) @@ -78,15 +63,29 @@ MediaBuyDelivery, NotificationType, ) +from adcp.types.generated_poc.media_buy.get_products_request import GetProductsRequest from adcp.types.generated_poc.media_buy.get_products_response import GetProductsResponse +from adcp.types.generated_poc.media_buy.list_creative_formats_request import ( + ListCreativeFormatsRequest, +) from adcp.types.generated_poc.media_buy.list_creative_formats_response import ( CreativeAgent, ListCreativeFormatsResponse, ) +from adcp.types.generated_poc.media_buy.list_creatives_request import ( + FieldModel, + ListCreativesRequest, + Sort, +) from adcp.types.generated_poc.media_buy.list_creatives_response import ( Creative, ListCreativesResponse, ) +from adcp.types.generated_poc.media_buy.package_request import PackageRequest +from adcp.types.generated_poc.media_buy.package_update import ( + PackageUpdate1, + PackageUpdate2, +) def _apply_coercion() -> None: From f19d9afb755bc9a75543f42f10bb4d1c05e4ef5c Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Mon, 26 Jan 2026 06:44:45 -0500 Subject: [PATCH 03/13] feat: sync with ADCP 2.6 schema changes - Sync schemas from upstream adcontextprotocol.org - Consolidate pricing options (CpmAuction/CpmFixed -> CpmPricingOption, VcpmAuction/VcpmFixed -> VcpmPricingOption) - Consolidate PreviewRender (UrlPreviewRender/HtmlPreviewRender/BothPreviewRender -> unified PreviewRender) - Update type exports and aliases for backwards compatibility - Fix preview_cache.py to work with unified PreviewRender (no longer RootModel) - Update tests to reflect schema changes BREAKING CHANGE: CpmAuctionPricingOption, CpmFixedRatePricingOption, VcpmAuctionPricingOption, VcpmFixedRatePricingOption have been consolidated into CpmPricingOption and VcpmPricingOption respectively. Co-Authored-By: Claude Opus 4.5 --- schemas/cache/.hashes.json | 46 ++-- .../update-content-standards-response.json | 16 +- schemas/cache/core/pricing-option.json | 12 +- schemas/cache/core/product-filters.json | 2 +- schemas/cache/creative/preview-render.json | 258 +++--------------- schemas/cache/extensions/index.json | 2 +- schemas/cache/pricing-options/cpc-option.json | 52 +++- .../cache/pricing-options/cpcv-option.json | 52 +++- .../pricing-options/cpm-fixed-option.json | 51 ---- ...pm-auction-option.json => cpm-option.json} | 33 +-- schemas/cache/pricing-options/cpp-option.json | 56 ++-- schemas/cache/pricing-options/cpv-option.json | 56 ++-- .../pricing-options/flat-rate-option.json | 66 +++-- .../pricing-options/vcpm-fixed-option.json | 51 ---- ...m-auction-option.json => vcpm-option.json} | 33 +-- src/adcp/__init__.py | 14 +- src/adcp/types/__init__.py | 14 +- src/adcp/types/_ergonomic.py | 29 +- src/adcp/types/_generated.py | 33 +-- src/adcp/types/aliases.py | 21 +- .../update_content_standards_response.py | 12 +- .../generated_poc/core/pricing_option.py | 22 +- .../generated_poc/core/product_filters.py | 7 +- .../generated_poc/creative/preview_render.py | 134 ++------- .../pricing_options/cpc_option.py | 45 ++- .../pricing_options/cpcv_option.py | 45 ++- .../pricing_options/cpm_fixed_option.py | 43 --- .../{cpm_auction_option.py => cpm_option.py} | 42 +-- .../pricing_options/cpp_option.py | 55 ++-- .../pricing_options/cpv_option.py | 55 ++-- .../pricing_options/flat_rate_option.py | 84 +++--- .../pricing_options/vcpm_fixed_option.py | 47 ---- ...{vcpm_auction_option.py => vcpm_option.py} | 37 ++- src/adcp/utils/preview_cache.py | 3 +- tests/test_discriminated_unions.py | 76 ++---- tests/test_preview_html.py | 3 +- tests/test_public_api.py | 45 ++- tests/test_type_aliases.py | 12 +- tests/test_type_coercion.py | 7 +- 39 files changed, 665 insertions(+), 1006 deletions(-) delete mode 100644 schemas/cache/pricing-options/cpm-fixed-option.json rename schemas/cache/pricing-options/{cpm-auction-option.json => cpm-option.json} (66%) delete mode 100644 schemas/cache/pricing-options/vcpm-fixed-option.json rename schemas/cache/pricing-options/{vcpm-auction-option.json => vcpm-option.json} (68%) delete mode 100644 src/adcp/types/generated_poc/pricing_options/cpm_fixed_option.py rename src/adcp/types/generated_poc/pricing_options/{cpm_auction_option.py => cpm_option.py} (61%) delete mode 100644 src/adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py rename src/adcp/types/generated_poc/pricing_options/{vcpm_auction_option.py => vcpm_option.py} (61%) diff --git a/schemas/cache/.hashes.json b/schemas/cache/.hashes.json index 3207e58c..01ea267a 100644 --- a/schemas/cache/.hashes.json +++ b/schemas/cache/.hashes.json @@ -1,5 +1,5 @@ { - "https://adcontextprotocol.org/schemas/latest/index.json": "d8dd5cc61b2e7b7b351fbccf20288214b0f6eaa7e53d9708cdb8955a3f125db7", + "https://adcontextprotocol.org/schemas/latest/index.json": "0f2b374b1a022b320c53e29871336ec18f1a892f22e817d536ce11b7c3140237", "https://adcontextprotocol.org/schemas/latest/adagents.json": "585f06ed0f898c207531b208706d66fb2fe8c184355e8e332aa6dd14697cb537", "https://adcontextprotocol.org/schemas/latest/content-standards/artifact-webhook-payload.json": "a5ddff12ff1d6316636919bc87359980512e63ff688d4b742628ab06b91b537b", "https://adcontextprotocol.org/schemas/latest/content-standards/artifact.json": "b499571575b8e0f11b5c21dd32189fd19191d32a795cff225165fdfd0092917b", @@ -12,10 +12,9 @@ "https://adcontextprotocol.org/schemas/latest/content-standards/get-content-standards-response.json": "2b857288ce95461fd5e278fe27d6a21dbb06c442ee2a8f41db2530e547280991", "https://adcontextprotocol.org/schemas/latest/content-standards/get-media-buy-artifacts-request.json": "62866c85ca88dd674c89b9be02e875b599265875368802b6a8c7c8564bd4c607", "https://adcontextprotocol.org/schemas/latest/content-standards/get-media-buy-artifacts-response.json": "bdac754a8fafed7152bbafc42bfa4abf2ed85b6e8feb5ac952be731748ecd751", - "https://adcontextprotocol.org/schemas/latest/content-standards/list-content-standards-request.json": "0a877b8ecdc7b95fff4943a51f79b0f73a145dbe29914b3b94a85ac7490ea051", "https://adcontextprotocol.org/schemas/latest/content-standards/list-content-standards-response.json": "9a1add4101da91e188e95a893ae50ec6c7eae6b3dc9cecb14c9edddf0a9a4c2b", "https://adcontextprotocol.org/schemas/latest/content-standards/update-content-standards-request.json": "b0b5ad96853c0f90870716ae855b2d683d168859cab32d1f67afed7e734c014a", - "https://adcontextprotocol.org/schemas/latest/content-standards/update-content-standards-response.json": "b309ab5a2e0b666e4ecb1d5d4c29bd8992f469bbcff39368dfd8bce1386a2fe6", + "https://adcontextprotocol.org/schemas/latest/content-standards/update-content-standards-response.json": "68b2307f5a152df438f8b406873292947d477cd1d8e392a074ac5b7f61dfd190", "https://adcontextprotocol.org/schemas/latest/content-standards/validate-content-delivery-request.json": "5744995b40f3ca06a6ba7e33471bfa2ad4358ddf12788b4f53faaf79b27b47e7", "https://adcontextprotocol.org/schemas/latest/content-standards/validate-content-delivery-response.json": "a3223d796114054b90a67ebff460286a5231f956cfbbfae2398fef518dfe3b55", "https://adcontextprotocol.org/schemas/latest/core/activation-key.json": "a31fb82057c50037575304641bcb32999239a762d93c1b3f1c5f535678c898a6", @@ -39,6 +38,7 @@ "https://adcontextprotocol.org/schemas/latest/core/creative-filters.json": "0095157d0cfe6fcff2299f438a9f27e6d9c9cde23174034526a9974e228ad05b", "https://adcontextprotocol.org/schemas/latest/core/creative-manifest.json": "e340b49ab2ab88ead4698a5fccde77cd0bbb288e5594b1f97647e66a7593ba96", "https://adcontextprotocol.org/schemas/latest/core/creative-policy.json": "c63d0489e8d7423b49471b3ceeae3df6716e5313a842bdf881dfa4e1f3516e6c", + "https://adcontextprotocol.org/schemas/latest/core/delivery-metrics.json": "119af3303ff6c53099bfd2ff5d2131ae634a7c53a1f914a6f05d963662e7b2a3", "https://adcontextprotocol.org/schemas/latest/core/deployment.json": "5769c02297e584f761a55301732621e22f8166e9806a1933cb842c1be9902914", "https://adcontextprotocol.org/schemas/latest/core/destination.json": "007880839e1d556972365ba1cd7076d081bbd6e6b9b0ba47147fc2748ce60d35", "https://adcontextprotocol.org/schemas/latest/core/error.json": "97dadd80893ba1c3d371e7b3fefe33941e3b8e660e91d0e8e1517c5144851b1d", @@ -55,15 +55,14 @@ "https://adcontextprotocol.org/schemas/latest/core/package.json": "ed37f06989f3936fda9caf03201ffe30b120a4bb47251c3fd85e5cad341737fc", "https://adcontextprotocol.org/schemas/latest/core/performance-feedback.json": "63dec657c26dd2702d9051d151d428b97ce8ad427fea8571c571a8eb8f53d99c", "https://adcontextprotocol.org/schemas/latest/core/placement.json": "2b5a7cd544e2ef14d03149b3fc47700ca4559604c5bc0c233bf44e2b2e8b50ca", - "https://adcontextprotocol.org/schemas/latest/core/pricing-option.json": "f4f99dac2a28722dd3ce0ded62e8b93a295ba5fff43de6c3d1419e0cfccf4e12", + "https://adcontextprotocol.org/schemas/latest/core/pricing-option.json": "11b520fa07e90333a65741f85cecdd2186bc83fa0fa30a9101128cd1c5b92cc6", "https://adcontextprotocol.org/schemas/latest/core/product-allocation.json": "736a415a81e9e28337975eb5c7d948e4edc3512b2bcca9331656993e86418d30", - "https://adcontextprotocol.org/schemas/latest/core/product-filters.json": "d067711fb1cca672d70a1340ebd4d9a59cdcba591c521e229f27770764668af3", + "https://adcontextprotocol.org/schemas/latest/core/product-filters.json": "b50b158cfc3a39cbf7a5d28da2f4fd1564daf0fc72afcf35d76ea1db1b0c3212", "https://adcontextprotocol.org/schemas/latest/core/product.json": "3c7cedff87c61f2761e61a381063e9bb4ed90a8578f6a415566aadf57d0afff4", "https://adcontextprotocol.org/schemas/latest/core/promoted-offerings.json": "cb9976da4643b54ca64284a25b7a8478935d196f0eaf1453cd9b369678b1065e", "https://adcontextprotocol.org/schemas/latest/core/promoted-products.json": "8046efb31fb8e0c8c009123591a5446ee9db684f20f9d46c5f3f7e78492231b9", "https://adcontextprotocol.org/schemas/latest/core/property-id.json": "16ff353402c03691a7290a0f7578a901b63a0f7e83567b8903c5c6f89e1fb6f0", "https://adcontextprotocol.org/schemas/latest/core/property-list-ref.json": "50c908159f9d02bff2a3330ac1bdbe2a46c47649a3efbc0a8eb9f8118b3b70bc", - "https://adcontextprotocol.org/schemas/latest/core/property-tag.json": "6f2c35324ca6c5533a2c3d1a5837360c813a0905be68b11da7a46965ec37d59c", "https://adcontextprotocol.org/schemas/latest/core/property.json": "f81a2eefccc2ebf38db5c08a6aa99935fb03736a5abc946a4a4aa72a47015349", "https://adcontextprotocol.org/schemas/latest/core/proposal.json": "440619ed4ef8dfb877509ea2e383b130d22a0f3e5422916ddf8f51212fba7754", "https://adcontextprotocol.org/schemas/latest/core/protocol-envelope.json": "38fca1729f9a8cd242b5f081559f195b097bb3e0f36456a53af30d0c8212015c", @@ -71,6 +70,7 @@ "https://adcontextprotocol.org/schemas/latest/core/push-notification-config.json": "64ed4db710d5a5346d6935e238d28ffaa4374dcff9d08e5d4283d4786dfe6de5", "https://adcontextprotocol.org/schemas/latest/core/reporting-capabilities.json": "6aad28b1d8a7793035cb97c0b92e569ca6caae7def439a679169519764fbe2b2", "https://adcontextprotocol.org/schemas/latest/core/reporting-webhook.json": "90e90d454334590670cfb881b14be00dd2a7fc134b0cc4494c79c6848fc2db1d", + "https://adcontextprotocol.org/schemas/latest/core/response.json": "232e6fc35a8dec7e7ad0743cd9be807cd7143e32eeb162f830ab692347744967", "https://adcontextprotocol.org/schemas/latest/core/signal-filters.json": "e2558d771937cdaef2fb278db6bc56e57078aeafacc1c0d83cfd378b17812117", "https://adcontextprotocol.org/schemas/latest/core/start-timing.json": "8e07e0469f434f3d3ba998e2b1fe58fc3dd097915e2d5e0c547cadfd5a469158", "https://adcontextprotocol.org/schemas/latest/core/sub-asset.json": "c0293416fd0275afd5ef59bd68675ff8ea37e4d4ba8f3a13e375711529a6399a", @@ -80,7 +80,6 @@ "https://adcontextprotocol.org/schemas/latest/creative/list-creative-formats-response.json": "160adbe2020191bd6ded0b094ea6a2e5ca9cb814f468e1bb70326ee59b7df1a3", "https://adcontextprotocol.org/schemas/latest/creative/preview-creative-request.json": "5f4f3095501e3fb1fd8f46815d963326a57b452c85b6c42ed4dc64cf8b928029", "https://adcontextprotocol.org/schemas/latest/creative/preview-creative-response.json": "caf1adb408cb6f9e07ab8eb33f683af118294f632cb39e1deaa8d92beb846056", - "https://adcontextprotocol.org/schemas/latest/creative/preview-render.json": "b4837c5a4027d7034f90ddf914c2e5e1a90e4ba6ee76f68a1b622e8a6cf64fc3", "https://adcontextprotocol.org/schemas/latest/enums/adcp-domain.json": "5f13f5da2b16c09e2b99ba8960356a03c92f6fb7758abe3ec33ff46050e78eba", "https://adcontextprotocol.org/schemas/latest/enums/asset-content-type.json": "74414bc886efb8a52794da63cfbb873befd9d24c87d9293ac88008bd496dfafc", "https://adcontextprotocol.org/schemas/latest/enums/auth-scheme.json": "492732201479760e022e7e20461874312403dab836af0f45c1382fd7b59c8b17", @@ -101,20 +100,19 @@ "https://adcontextprotocol.org/schemas/latest/enums/format-id-parameter.json": "0783749a5ac1e2eff4cc523eec16e3a723e107b3718bd55e1bc671cf230b0a1f", "https://adcontextprotocol.org/schemas/latest/enums/frequency-cap-scope.json": "3275a767cbde71235e7a23d0d775b5d58afb1859936393b04eb2c7c976ef2493", "https://adcontextprotocol.org/schemas/latest/enums/geo-level.json": "e6b65de7e6699c4171eba799553a39f8d3bdc787242ef7bfa269b6f6d77a1bfa", - "https://adcontextprotocol.org/schemas/latest/enums/history-entry-type.json": "e77c87be1493e84d83ffb567113303e2b50baa1dbd8c1ea791e2e8822f2bbf64", "https://adcontextprotocol.org/schemas/latest/enums/http-method.json": "75c12b6e8868b0248841bbf8e666fd097308276f59a2c8f809fa279a88c06188", "https://adcontextprotocol.org/schemas/latest/enums/identifier-types.json": "73190ea41c388af5b6b9c56358c4bce893b0f7cf61bc5062647f9987755451ed", "https://adcontextprotocol.org/schemas/latest/enums/javascript-module-type.json": "da4746acdce608ce9497f59e7fdbc97a649367e55aebe4b9675feb3176e8525e", "https://adcontextprotocol.org/schemas/latest/enums/landing-page-requirement.json": "5a09b76855c541b23ccf1aaa8ea87e77203d358b5c01c1b255722f21ac6327a4", "https://adcontextprotocol.org/schemas/latest/enums/markdown-flavor.json": "df8836754968fb1c02fc7725aa1bce56e315c4cec11515a19058b5d6a0cf782b", "https://adcontextprotocol.org/schemas/latest/enums/media-buy-status.json": "70bd2fca8832137c3b504c4b80934fdf8a57bcb45c4e1bf821fc49096aae53f9", - "https://adcontextprotocol.org/schemas/latest/enums/metric-type.json": "41eafcfaf6206670aabecd65abd5c1f2d0c4af019a3e4055d26aecfdccfd0a75", "https://adcontextprotocol.org/schemas/latest/enums/metro-system.json": "f8cde6b0bd45c4fbabef8ff90e01c57ffc8d5a821d7f50b94de48a6ed7cf1641", + "https://adcontextprotocol.org/schemas/latest/enums/notification-type.json": "be6d4177c9350e8fdced52773b483acf464beecd567934cf020e53c43e61afac", "https://adcontextprotocol.org/schemas/latest/enums/pacing.json": "6fb8e62bfdc40bb48e0620ed71310f21a821fdfbe644c625d01b6a68ba4e40bb", "https://adcontextprotocol.org/schemas/latest/enums/postal-system.json": "20651c3197e7554ced864c3addb71a27ac257952988e5248db8f6f882fad12d6", "https://adcontextprotocol.org/schemas/latest/enums/preview-output-format.json": "b14841f4e6689b3a3d2afa5740b4787ba49961d39ede2f9b92b709ad7970b32e", - "https://adcontextprotocol.org/schemas/latest/enums/pricing-model.json": "eb2aee267593d91e7f02ee0143fd8c2226021560fbee6b7ad983188f216f5f5a", "https://adcontextprotocol.org/schemas/latest/enums/property-type.json": "7e047eb116c41b4682818f89c8b19573636a546500289d48be189945318ded83", + "https://adcontextprotocol.org/schemas/latest/enums/publisher-identifier-types.json": "3d4f8baf9ea57f525d1f126d58190588c17b05c7493ea2c9ff5737922cc96c4d", "https://adcontextprotocol.org/schemas/latest/enums/reporting-frequency.json": "b480016e39a0b8a4493e55f5bda13b153e8df7c4c07ee49586cd77bdfdab0af5", "https://adcontextprotocol.org/schemas/latest/enums/signal-catalog-type.json": "f899ae2550950b3e2269f42c20c50bfd09c1f2870fc656e334b73758bfbf2245", "https://adcontextprotocol.org/schemas/latest/enums/sort-direction.json": "85a2cf23403297069995f14498a495c566a5a8bce4409d468d9071e18338ce6e", @@ -128,14 +126,13 @@ "https://adcontextprotocol.org/schemas/latest/enums/webhook-response-type.json": "72ba18db0a6fabd814195e895841e4cd6af5b54c4d6a954552c36284da5c4075", "https://adcontextprotocol.org/schemas/latest/enums/webhook-security-method.json": "80c1a7622b750af3bcfd2695569a3b348e42d5c8614378c27a65f8c7374e9165", "https://adcontextprotocol.org/schemas/latest/extensions/extension-meta.json": "639103027d657206b40a9bdfff0baded2588835e6f15e5b0f7acfec748e94423", - "https://adcontextprotocol.org/schemas/latest/extensions/index.json": "7dd5e1b375a9f55d0f87313858fadf169e869d1802f16aed296d70247184007a", + "https://adcontextprotocol.org/schemas/latest/extensions/index.json": "60db88edbb93cd31cd0d41b3f0dc31fc9b3afd6f9d39cc49fbb7226b50fe0687", "https://adcontextprotocol.org/schemas/latest/media-buy/build-creative-request.json": "0eadf98c199f8b29475a600cd9bf6d71cd6adb135c4e2d65cf7a0ec8efb5f566", "https://adcontextprotocol.org/schemas/latest/media-buy/build-creative-response.json": "67c3e0d4b3f0c641e7e86833ab5e54c872d9cc79e673bf414abb412c81853973", "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-async-response-input-required.json": "397bb7a973f943bdb2c53b36822c93ecdc815d3e5184a1129cad8648d88f378a", "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-async-response-submitted.json": "7c9502344a561c3aca8752e6d95918444eb905b82413af0c6a8e4782963ce4f2", "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-async-response-working.json": "f8023b1dd59955843ecf2ee3c79a81ca83411ced35daa58a6e7210ad88678e00", "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-request.json": "b0fe4b12e80e79dc7269281e627ae0882ccd5d5b48520563209be24f359eac0d", - "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-response.json": "02e3fb22715890ede07cf7fa976b2d2025754b3cb88aa68be3c3479fdb7bbea5", "https://adcontextprotocol.org/schemas/latest/media-buy/get-media-buy-delivery-request.json": "4c2c5c3daeadec0dd8c5f3284cbd552905cf3987b10135ffb3bb87f05584c229", "https://adcontextprotocol.org/schemas/latest/media-buy/get-media-buy-delivery-response.json": "6abd494e57bd0f43ad5089bc438d116e9c74892791c3fbb9db669e859627457c", "https://adcontextprotocol.org/schemas/latest/media-buy/get-products-async-response-input-required.json": "107e27baf08f80a97a0de83a24faaf37cae5c0c3112ba707ff191af1c2ad4ea6", @@ -150,30 +147,26 @@ "https://adcontextprotocol.org/schemas/latest/media-buy/list-creatives-request.json": "d45bc1bdcc9dca066c2430992b30dd6c9b37ce667957bdc2d1048cbe250b7a4c", "https://adcontextprotocol.org/schemas/latest/media-buy/list-creatives-response.json": "9fe8f7628332bb3a4c6f146529b34a609cb210918bac7e058dd39835a007384f", "https://adcontextprotocol.org/schemas/latest/media-buy/package-request.json": "11d3ac74b3d07a2b16165f34cbebed8e688565115e45c722dedf1d0663f8d819", - "https://adcontextprotocol.org/schemas/latest/media-buy/package-update.json": "6cd7b8089cd0b3179ef66b161f9bdd6a42dd6007be7401bbc0a96bbd48337bee", "https://adcontextprotocol.org/schemas/latest/media-buy/provide-performance-feedback-request.json": "8fff8a6e58cf2f8dd95e2e1cb53ef1b3c2154991a577547a2f8c75028867a81b", "https://adcontextprotocol.org/schemas/latest/media-buy/provide-performance-feedback-response.json": "bebd13943d48ad8e8b419bd69f9fa2a9b4df30c379ae74219904e698231e7371", - "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-async-response-input-required.json": "62b4e86135542f4076b7bcf6edf157a7bb919e168ea97d0afb1ef1fe4ff2b8dd", "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-async-response-submitted.json": "0a6df44b4224a4b38d25673d0f813022e124c7ac0bcc7eccb95e673849af7368", "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-async-response-working.json": "5a336a8217d13fa112ac3dd1ed2d2c707f8abd9bb9ff05af674c22138dc24c90", "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-request.json": "01cfece0e07ba8825656aec890bd2e9293918d41695d777ca70d684f626d19d6", "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-response.json": "1fc6bf8348c520aaf2ec2041b64f50307de7edc30e54dc0de81e36af88e2833f", "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-async-response-input-required.json": "73ecee00cf0babc200778621b78148a54327df3436dedf349d83c734a99fc4e4", - "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-async-response-submitted.json": "d4736323140cf6db5522e1de5aeb1023f8a7b608d319ede26b86d28c57bea0ef", "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-async-response-working.json": "ccca3256ac3179a2125922718efde61367b9046bdfdee156bdaa72c1398f2ed3", "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-request.json": "11ab339a8e3dae8a5f0d9df0b680eb7acfe96c294922b5b1678e6e302c1f6b76", - "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-response.json": "aca3e048a43704e0f7dee2370c4ad4c4b662805e4fe39b3dde7cfea3bba1101c", - "https://adcontextprotocol.org/schemas/latest/pricing-options/cpc-option.json": "dcd9048d2eb46871c101f9167af24c0a3d28f291d3e5fd9f77281c0460921f5f", - "https://adcontextprotocol.org/schemas/latest/pricing-options/cpcv-option.json": "7de0c760be37a96ae526de23c9312506bd15a924d42cb4621d48b4ee156dbb83", - "https://adcontextprotocol.org/schemas/latest/pricing-options/cpm-auction-option.json": "1a45dbe8390ce10e58b7485bd1feb2d9b399fd2fdf25363c783b38b56959750c", - "https://adcontextprotocol.org/schemas/latest/pricing-options/cpm-fixed-option.json": "c02d668c229fc0a5f959cab122008298a3b515afcc4ba0d6bc90a5a838667e39", - "https://adcontextprotocol.org/schemas/latest/pricing-options/cpp-option.json": "fd571e844444d2e6de3ea2e1595dc66d1d06d28346cfe3e1af856f716b541215", - "https://adcontextprotocol.org/schemas/latest/pricing-options/cpv-option.json": "75e6545731c747c4e0ab5522239700991de91fc91739b988855cc6e89c36f38f", - "https://adcontextprotocol.org/schemas/latest/pricing-options/flat-rate-option.json": "515ec3319bb25437f8302c6ee89e51d1164e14d6a88d0a60391ad2184f8e0430", - "https://adcontextprotocol.org/schemas/latest/pricing-options/vcpm-auction-option.json": "ae7f4d71b43e51a8eb7411bd0509a6b1618834ac28b6c74af31ffd3cf47f2f55", - "https://adcontextprotocol.org/schemas/latest/pricing-options/vcpm-fixed-option.json": "0ae515fd9be111cd8bbd6029f2ffcb0afaaf565c1fcf96a483f5fa98cb993cee", + "https://adcontextprotocol.org/schemas/latest/pricing-options/cpc-option.json": "a0c5d6d801932b92df96e422d20d7c19c9d678f741fa7f273e2d1d7ca297499f", + "https://adcontextprotocol.org/schemas/latest/pricing-options/cpcv-option.json": "d4533d055f304024097eca3988df2530e532f2b4a19e4cbda0d9d3555545c059", + "https://adcontextprotocol.org/schemas/latest/pricing-options/cpm-option.json": "345bc9fa5cb3c5615da7fa1f02d29ff1c82e4464a55d523bb40d02db6af9427d", + "https://adcontextprotocol.org/schemas/latest/pricing-options/cpp-option.json": "f670e68a8808ca3a2f596c71ab5fc917f774fb14e1c53affba7c01bed79a138f", + "https://adcontextprotocol.org/schemas/latest/pricing-options/cpv-option.json": "94cebd35c0fb63d746483a445856e4da46bc9a4961b4f008049b991fa56ffa15", + "https://adcontextprotocol.org/schemas/latest/pricing-options/flat-rate-option.json": "7bf0dc8f224dda20fa9b97aca203af6ffbb9ed76bd5d5c1462235dd5cfd57ab6", + "https://adcontextprotocol.org/schemas/latest/pricing-options/vcpm-option.json": "f896630167dd7bda4b7fccbab451b6208e91c50facd5c283e8eaf4883fab5e4f", + "https://adcontextprotocol.org/schemas/latest/property/base-property-source.json": "4953f7bae585927f806926fbbac096b1a9f1e08df97ae81071233f6eb96462a0", "https://adcontextprotocol.org/schemas/latest/property/create-property-list-request.json": "9b96c2cbe21edce3c6645c7bf7947399cc86cb8cc72b236a862150d6d79e5482", "https://adcontextprotocol.org/schemas/latest/property/create-property-list-response.json": "b7ceada500f573191cd0ef9e07817cb35f5e1b2dc1180cb15a231db460ee1655", + "https://adcontextprotocol.org/schemas/latest/property/delete-property-list-request.json": "5713450eb83436a1cf90a5636f6b54a1b0c5ffd1a15c481bca462000c4d05dd3", "https://adcontextprotocol.org/schemas/latest/property/delete-property-list-response.json": "222fff1b07bd9d20ce0a4db6a723ed7d86b9b34ea9e5139394c444275586c4e5", "https://adcontextprotocol.org/schemas/latest/property/feature-requirement.json": "16e9f8f0f8a3e5150f264698be1ec1a68aba0999cf5d6c11ce26b2d0bc72bedb", "https://adcontextprotocol.org/schemas/latest/property/get-property-list-request.json": "99edd1056bd089fc32967b42f8e33dbb90b68e46ff8a2d9a627e5ec79aeb47ed", @@ -199,10 +192,9 @@ "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-get-offering-request.json": "953346b451471a4c930649fb5dc470361763009b1a2efa0f4666a0b7acfb16c9", "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-get-offering-response.json": "e0cc6da05594aa7080319bbc506cf56d3f7c541504cde86e27573917078410e8", "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-identity.json": "6b1fad0cb8433b15055b7e2a8271d7ee1ac405db6f5e19bb9aa8eb405a747797", + "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-initiate-session-request.json": "dd872808799aa225cb7c5723d162aaa21c3265b84f26ebb13dd12b4b6076b26c", "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-initiate-session-response.json": "3eb8440b2be7b8d4777003b34f3094fd6d1c6b87a3236163d584192352b0c7f7", - "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-send-message-request.json": "b8a789094d4288cf277070e762f01bb22b3248c9730797603974891741bbc3a4", "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-send-message-response.json": "6c3e693333c009d37a45678ce73d9b3ee0bcb7ea3a4089187f0ab422dd04df97", "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-terminate-session-request.json": "8121c3cbf497bef6e5b265a3520daa8cb1c38cd133e8d593b4558f175f7fab95", - "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-terminate-session-response.json": "446b2ff92b8522d805af1592334d56c045e891608bc87f751007c8afe552d188", "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-ui-element.json": "e7d434246c38e1d047896cfdfec30ffda5f842ea8a4f699c5701c6c7c22bfaf8" } \ No newline at end of file diff --git a/schemas/cache/content-standards/update-content-standards-response.json b/schemas/cache/content-standards/update-content-standards-response.json index 3eb265d6..e160948a 100644 --- a/schemas/cache/content-standards/update-content-standards-response.json +++ b/schemas/cache/content-standards/update-content-standards-response.json @@ -13,21 +13,7 @@ "errors": { "description": "Errors that occurred during the update", "items": { - "properties": { - "code": { - "description": "Error code (e.g., STANDARDS_NOT_FOUND, SCOPE_CONFLICT)", - "type": "string" - }, - "message": { - "description": "Human-readable error message", - "type": "string" - } - }, - "required": [ - "code", - "message" - ], - "type": "object" + "$ref": "../core/error.json" }, "type": "array" }, diff --git a/schemas/cache/core/pricing-option.json b/schemas/cache/core/pricing-option.json index 3386fa3b..33de20cd 100644 --- a/schemas/cache/core/pricing-option.json +++ b/schemas/cache/core/pricing-option.json @@ -1,18 +1,12 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "description": "A pricing model option offered by a publisher for a product. Each pricing model has its own schema with model-specific requirements.", + "description": "A pricing model option offered by a publisher for a product. Discriminated by pricing_model field. If fixed_price is present, it's fixed pricing. If absent, it's auction-based (floor_price and price_guidance optional).", "oneOf": [ { - "$ref": "../pricing-options/cpm-fixed-option.json" + "$ref": "../pricing-options/cpm-option.json" }, { - "$ref": "../pricing-options/cpm-auction-option.json" - }, - { - "$ref": "../pricing-options/vcpm-fixed-option.json" - }, - { - "$ref": "../pricing-options/vcpm-auction-option.json" + "$ref": "../pricing-options/vcpm-option.json" }, { "$ref": "../pricing-options/cpc-option.json" diff --git a/schemas/cache/core/product-filters.json b/schemas/cache/core/product-filters.json index 3ea939de..47f1be4c 100644 --- a/schemas/cache/core/product-filters.json +++ b/schemas/cache/core/product-filters.json @@ -78,7 +78,7 @@ "type": "array" }, "is_fixed_price": { - "description": "Filter for fixed price vs auction products", + "description": "Filter by pricing availability: true = products offering fixed pricing (at least one option with fixed_price), false = products offering auction pricing (at least one option without fixed_price). Products with both fixed and auction options match both true and false.", "type": "boolean" }, "metros": { diff --git a/schemas/cache/creative/preview-render.json b/schemas/cache/creative/preview-render.json index 509aaf91..c3893e39 100644 --- a/schemas/cache/creative/preview-render.json +++ b/schemas/cache/creative/preview-render.json @@ -1,224 +1,54 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "description": "A single rendered piece of a creative preview with discriminated output format", - "oneOf": [ - { - "additionalProperties": true, - "description": "URL-only preview format", - "properties": { - "dimensions": { - "description": "Dimensions for this rendered piece", - "properties": { - "height": { - "minimum": 0, - "type": "number" - }, - "width": { - "minimum": 0, - "type": "number" - } - }, - "required": [ - "width", - "height" - ], - "type": "object" - }, - "embedding": { - "description": "Optional security and embedding metadata for safe iframe integration", - "properties": { - "csp_policy": { - "description": "Content Security Policy requirements for embedding", - "type": "string" - }, - "recommended_sandbox": { - "description": "Recommended iframe sandbox attribute value (e.g., 'allow-scripts allow-same-origin')", - "type": "string" - }, - "requires_https": { - "description": "Whether this output requires HTTPS for secure embedding", - "type": "boolean" - }, - "supports_fullscreen": { - "description": "Whether this output supports fullscreen mode", - "type": "boolean" - } - }, - "type": "object" - }, - "output_format": { - "const": "url", - "description": "Discriminator indicating preview_url is provided", - "type": "string" - }, - "preview_url": { - "description": "URL to an HTML page that renders this piece. Can be embedded in an iframe.", - "format": "uri", - "type": "string" - }, - "render_id": { - "description": "Unique identifier for this rendered piece within the variant", - "type": "string" - }, - "role": { - "description": "Semantic role of this rendered piece. Use 'primary' for main content, 'companion' for associated banners, descriptive strings for device variants or custom roles.", - "type": "string" - } - }, - "required": [ - "render_id", - "output_format", - "preview_url", - "role" - ], - "type": "object" + "title": "Preview Render", + "description": "A single rendered piece of a preview. Most formats render as a single piece, but companion ad formats, multi-placement formats, and adaptive formats may render as multiple pieces.", + "type": "object", + "additionalProperties": true, + "properties": { + "render_id": { + "type": "string", + "description": "Unique identifier for this render piece" }, - { - "additionalProperties": true, - "description": "HTML-only preview format", - "properties": { - "dimensions": { - "description": "Dimensions for this rendered piece", - "properties": { - "height": { - "minimum": 0, - "type": "number" - }, - "width": { - "minimum": 0, - "type": "number" - } - }, - "required": [ - "width", - "height" - ], - "type": "object" - }, - "embedding": { - "description": "Optional security and embedding metadata", - "properties": { - "csp_policy": { - "description": "Content Security Policy requirements for embedding", - "type": "string" - }, - "recommended_sandbox": { - "description": "Recommended iframe sandbox attribute value (e.g., 'allow-scripts allow-same-origin')", - "type": "string" - }, - "requires_https": { - "description": "Whether this output requires HTTPS for secure embedding", - "type": "boolean" - }, - "supports_fullscreen": { - "description": "Whether this output supports fullscreen mode", - "type": "boolean" - } - }, - "type": "object" - }, - "output_format": { - "const": "html", - "description": "Discriminator indicating preview_html is provided", - "type": "string" - }, - "preview_html": { - "description": "Raw HTML for this rendered piece. Can be embedded directly in the page without iframe. Security warning: Only use with trusted creative agents as this bypasses iframe sandboxing.", - "type": "string" - }, - "render_id": { - "description": "Unique identifier for this rendered piece within the variant", - "type": "string" - }, - "role": { - "description": "Semantic role of this rendered piece. Use 'primary' for main content, 'companion' for associated banners, descriptive strings for device variants or custom roles.", - "type": "string" - } - }, - "required": [ - "render_id", - "output_format", - "preview_html", - "role" - ], - "type": "object" + "preview_url": { + "type": "string", + "format": "uri", + "description": "URL to the rendered preview HTML page that can be embedded in an iframe" }, - { - "additionalProperties": true, - "description": "Both URL and HTML preview format", + "dimensions": { + "type": "object", + "description": "Dimensions of this render piece", "properties": { - "dimensions": { - "description": "Dimensions for this rendered piece", - "properties": { - "height": { - "minimum": 0, - "type": "number" - }, - "width": { - "minimum": 0, - "type": "number" - } - }, - "required": [ - "width", - "height" - ], - "type": "object" - }, - "embedding": { - "description": "Optional security and embedding metadata for safe iframe integration", - "properties": { - "csp_policy": { - "description": "Content Security Policy requirements for embedding", - "type": "string" - }, - "recommended_sandbox": { - "description": "Recommended iframe sandbox attribute value (e.g., 'allow-scripts allow-same-origin')", - "type": "string" - }, - "requires_https": { - "description": "Whether this output requires HTTPS for secure embedding", - "type": "boolean" - }, - "supports_fullscreen": { - "description": "Whether this output supports fullscreen mode", - "type": "boolean" - } - }, - "type": "object" - }, - "output_format": { - "const": "both", - "description": "Discriminator indicating both preview_url and preview_html are provided", - "type": "string" - }, - "preview_html": { - "description": "Raw HTML for this rendered piece. Can be embedded directly in the page without iframe. Security warning: Only use with trusted creative agents as this bypasses iframe sandboxing.", - "type": "string" - }, - "preview_url": { - "description": "URL to an HTML page that renders this piece. Can be embedded in an iframe.", - "format": "uri", - "type": "string" - }, - "render_id": { - "description": "Unique identifier for this rendered piece within the variant", - "type": "string" - }, - "role": { - "description": "Semantic role of this rendered piece. Use 'primary' for main content, 'companion' for associated banners, descriptive strings for device variants or custom roles.", - "type": "string" + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels" + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels" } }, "required": [ - "render_id", - "output_format", - "preview_url", - "preview_html", - "role" - ], - "type": "object" + "width", + "height" + ] + }, + "placement_hint": { + "type": "string", + "description": "Optional hint about where this piece should be placed (e.g., 'main', 'companion', 'banner')" + }, + "media_type": { + "type": "string", + "description": "MIME type of the preview content", + "examples": [ + "text/html", + "image/png", + "video/mp4" + ] } - ], - "title": "Preview Render" + }, + "required": [ + "preview_url" + ] } \ No newline at end of file diff --git a/schemas/cache/extensions/index.json b/schemas/cache/extensions/index.json index e4bc98e7..82a84e30 100644 --- a/schemas/cache/extensions/index.json +++ b/schemas/cache/extensions/index.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "_generated": true, - "_generatedAt": "2026-01-25T18:43:29.083Z", + "_generatedAt": "2026-01-25T21:52:05.773Z", "description": "Auto-generated registry of formal AdCP extensions. Extensions provide typed schemas for vendor-specific or domain-specific data within the ext field. Agents declare which extensions they support in their agent card.", "extensions": {}, "title": "AdCP Extension Registry" diff --git a/schemas/cache/pricing-options/cpc-option.json b/schemas/cache/pricing-options/cpc-option.json index 26ede76e..0e3806eb 100644 --- a/schemas/cache/pricing-options/cpc-option.json +++ b/schemas/cache/pricing-options/cpc-option.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, - "description": "Cost Per Click fixed-rate pricing for performance-driven advertising campaigns", + "description": "Cost Per Click pricing. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", "properties": { "currency": { "description": "ISO 4217 currency code", @@ -14,37 +14,61 @@ "pattern": "^[A-Z]{3}$", "type": "string" }, - "is_fixed": { - "const": true, - "description": "Whether this is a fixed rate (true) or auction-based (false)", - "type": "boolean" + "fixed_price": { + "description": "Fixed price per click. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0, + "type": "number" + }, + "floor_price": { + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0, + "type": "number" }, "min_spend_per_package": { "description": "Minimum spend requirement per package using this pricing option, in the specified currency", "minimum": 0, "type": "number" }, + "price_guidance": { + "description": "Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "properties": { + "p25": { + "description": "25th percentile of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p50": { + "description": "Median of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p75": { + "description": "75th percentile of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p90": { + "description": "90th percentile of recent winning bids", + "minimum": 0, + "type": "number" + } + }, + "type": "object" + }, "pricing_model": { "const": "cpc", "description": "Cost per click", "type": "string" }, "pricing_option_id": { - "description": "Unique identifier for this pricing option within the product (e.g., 'cpc_usd_fixed')", + "description": "Unique identifier for this pricing option within the product", "type": "string" - }, - "rate": { - "description": "Fixed CPC rate (cost per click)", - "minimum": 0, - "type": "number" } }, "required": [ "pricing_option_id", "pricing_model", - "rate", - "currency", - "is_fixed" + "currency" ], "title": "CPC Pricing Option", "type": "object" diff --git a/schemas/cache/pricing-options/cpcv-option.json b/schemas/cache/pricing-options/cpcv-option.json index 064fa2ef..c0a76be1 100644 --- a/schemas/cache/pricing-options/cpcv-option.json +++ b/schemas/cache/pricing-options/cpcv-option.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, - "description": "Cost Per Completed View (100% video/audio completion) fixed-rate pricing", + "description": "Cost Per Completed View (100% video/audio completion) pricing. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", "properties": { "currency": { "description": "ISO 4217 currency code", @@ -14,37 +14,61 @@ "pattern": "^[A-Z]{3}$", "type": "string" }, - "is_fixed": { - "const": true, - "description": "Whether this is a fixed rate (true) or auction-based (false)", - "type": "boolean" + "fixed_price": { + "description": "Fixed price per completed view. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0, + "type": "number" + }, + "floor_price": { + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0, + "type": "number" }, "min_spend_per_package": { "description": "Minimum spend requirement per package using this pricing option, in the specified currency", "minimum": 0, "type": "number" }, + "price_guidance": { + "description": "Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "properties": { + "p25": { + "description": "25th percentile of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p50": { + "description": "Median of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p75": { + "description": "75th percentile of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p90": { + "description": "90th percentile of recent winning bids", + "minimum": 0, + "type": "number" + } + }, + "type": "object" + }, "pricing_model": { "const": "cpcv", "description": "Cost per completed view (100% completion)", "type": "string" }, "pricing_option_id": { - "description": "Unique identifier for this pricing option within the product (e.g., 'cpcv_usd_guaranteed')", + "description": "Unique identifier for this pricing option within the product", "type": "string" - }, - "rate": { - "description": "Fixed CPCV rate (cost per 100% completion)", - "minimum": 0, - "type": "number" } }, "required": [ "pricing_option_id", "pricing_model", - "rate", - "currency", - "is_fixed" + "currency" ], "title": "CPCV Pricing Option", "type": "object" diff --git a/schemas/cache/pricing-options/cpm-fixed-option.json b/schemas/cache/pricing-options/cpm-fixed-option.json deleted file mode 100644 index 279b4361..00000000 --- a/schemas/cache/pricing-options/cpm-fixed-option.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": true, - "description": "Cost Per Mille (cost per 1,000 impressions) with guaranteed fixed rate - common for direct/guaranteed deals", - "properties": { - "currency": { - "description": "ISO 4217 currency code", - "examples": [ - "USD", - "EUR", - "GBP", - "JPY" - ], - "pattern": "^[A-Z]{3}$", - "type": "string" - }, - "is_fixed": { - "const": true, - "description": "Whether this is a fixed rate (true) or auction-based (false)", - "type": "boolean" - }, - "min_spend_per_package": { - "description": "Minimum spend requirement per package using this pricing option, in the specified currency", - "minimum": 0, - "type": "number" - }, - "pricing_model": { - "const": "cpm", - "description": "Cost per 1,000 impressions", - "type": "string" - }, - "pricing_option_id": { - "description": "Unique identifier for this pricing option within the product (e.g., 'cpm_usd_guaranteed')", - "type": "string" - }, - "rate": { - "description": "Fixed CPM rate (cost per 1,000 impressions)", - "minimum": 0, - "type": "number" - } - }, - "required": [ - "pricing_option_id", - "pricing_model", - "rate", - "currency", - "is_fixed" - ], - "title": "CPM Fixed Rate Pricing Option", - "type": "object" -} \ No newline at end of file diff --git a/schemas/cache/pricing-options/cpm-auction-option.json b/schemas/cache/pricing-options/cpm-option.json similarity index 66% rename from schemas/cache/pricing-options/cpm-auction-option.json rename to schemas/cache/pricing-options/cpm-option.json index 8735617e..8cdc6c0e 100644 --- a/schemas/cache/pricing-options/cpm-auction-option.json +++ b/schemas/cache/pricing-options/cpm-option.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, - "description": "Cost Per Mille (cost per 1,000 impressions) with auction-based pricing - common for programmatic/non-guaranteed inventory", + "description": "Cost Per Mille (cost per 1,000 impressions) pricing. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", "properties": { "currency": { "description": "ISO 4217 currency code", @@ -14,10 +14,15 @@ "pattern": "^[A-Z]{3}$", "type": "string" }, - "is_fixed": { - "const": false, - "description": "Whether this is a fixed rate (true) or auction-based (false)", - "type": "boolean" + "fixed_price": { + "description": "Fixed price per unit. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0, + "type": "number" + }, + "floor_price": { + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0, + "type": "number" }, "min_spend_per_package": { "description": "Minimum spend requirement per package using this pricing option, in the specified currency", @@ -25,13 +30,8 @@ "type": "number" }, "price_guidance": { - "description": "Pricing guidance for auction-based CPM bidding", + "description": "Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", "properties": { - "floor": { - "description": "Minimum bid price - publisher will reject bids under this value", - "minimum": 0, - "type": "number" - }, "p25": { "description": "25th percentile winning price", "minimum": 0, @@ -53,9 +53,6 @@ "type": "number" } }, - "required": [ - "floor" - ], "type": "object" }, "pricing_model": { @@ -64,17 +61,15 @@ "type": "string" }, "pricing_option_id": { - "description": "Unique identifier for this pricing option within the product (e.g., 'cpm_usd_auction')", + "description": "Unique identifier for this pricing option within the product", "type": "string" } }, "required": [ "pricing_option_id", "pricing_model", - "price_guidance", - "currency", - "is_fixed" + "currency" ], - "title": "CPM Auction Pricing Option", + "title": "CPM Pricing Option", "type": "object" } \ No newline at end of file diff --git a/schemas/cache/pricing-options/cpp-option.json b/schemas/cache/pricing-options/cpp-option.json index 5be3c6a6..9b4c7885 100644 --- a/schemas/cache/pricing-options/cpp-option.json +++ b/schemas/cache/pricing-options/cpp-option.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, - "description": "Cost Per Point (Gross Rating Point) fixed-rate pricing for TV and audio campaigns requiring demographic measurement", + "description": "Cost Per Point (Gross Rating Point) pricing for TV and audio campaigns. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", "properties": { "currency": { "description": "ISO 4217 currency code", @@ -14,10 +14,15 @@ "pattern": "^[A-Z]{3}$", "type": "string" }, - "is_fixed": { - "const": true, - "description": "Whether this is a fixed rate (true) or auction-based (false)", - "type": "boolean" + "fixed_price": { + "description": "Fixed price per rating point. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0, + "type": "number" + }, + "floor_price": { + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0, + "type": "number" }, "min_spend_per_package": { "description": "Minimum spend requirement per package using this pricing option, in the specified currency", @@ -26,15 +31,15 @@ }, "parameters": { "additionalProperties": true, - "description": "CPP-specific parameters for demographic targeting and GRP requirements", + "description": "CPP-specific parameters for demographic targeting", "properties": { "demographic": { - "description": "Target demographic in Nielsen format: P/M/W/A/C + age range. Examples: P18-49 (Persons 18-49), M25-54 (Men 25-54), W35+ (Women 35+), A18-34 (Adults 18-34), C2-11 (Children 2-11)", + "description": "Target demographic in Nielsen format (P18-49, M25-54, W35+, etc.)", "pattern": "^[PMWAC][0-9]{2}(-[0-9]{2}|\\+)$", "type": "string" }, "min_points": { - "description": "Minimum GRPs/TRPs required for this pricing option", + "description": "Minimum GRPs/TRPs required", "minimum": 0, "type": "number" } @@ -44,27 +49,46 @@ ], "type": "object" }, + "price_guidance": { + "description": "Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "properties": { + "p25": { + "description": "25th percentile of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p50": { + "description": "Median of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p75": { + "description": "75th percentile of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p90": { + "description": "90th percentile of recent winning bids", + "minimum": 0, + "type": "number" + } + }, + "type": "object" + }, "pricing_model": { "const": "cpp", "description": "Cost per Gross Rating Point", "type": "string" }, "pricing_option_id": { - "description": "Unique identifier for this pricing option within the product (e.g., 'cpp_usd_p18-49')", + "description": "Unique identifier for this pricing option within the product", "type": "string" - }, - "rate": { - "description": "Fixed CPP rate (cost per rating point)", - "minimum": 0, - "type": "number" } }, "required": [ "pricing_option_id", "pricing_model", - "rate", "currency", - "is_fixed", "parameters" ], "title": "CPP Pricing Option", diff --git a/schemas/cache/pricing-options/cpv-option.json b/schemas/cache/pricing-options/cpv-option.json index e2fecdf9..58a0e67f 100644 --- a/schemas/cache/pricing-options/cpv-option.json +++ b/schemas/cache/pricing-options/cpv-option.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, - "description": "Cost Per View (at publisher-defined threshold) fixed-rate pricing for video/audio", + "description": "Cost Per View (at publisher-defined threshold) pricing for video/audio. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", "properties": { "currency": { "description": "ISO 4217 currency code", @@ -14,10 +14,15 @@ "pattern": "^[A-Z]{3}$", "type": "string" }, - "is_fixed": { - "const": true, - "description": "Whether this is a fixed rate (true) or auction-based (false)", - "type": "boolean" + "fixed_price": { + "description": "Fixed price per view. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0, + "type": "number" + }, + "floor_price": { + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0, + "type": "number" }, "min_spend_per_package": { "description": "Minimum spend requirement per package using this pricing option, in the specified currency", @@ -31,17 +36,17 @@ "view_threshold": { "oneOf": [ { - "description": "Percentage completion threshold for CPV pricing (0.0 to 1.0, e.g., 0.5 = 50% completion)", + "description": "Percentage completion threshold (0.0 to 1.0, e.g., 0.5 = 50%)", "maximum": 1, "minimum": 0, "type": "number" }, { "additionalProperties": true, - "description": "Time-based view threshold for CPV pricing", + "description": "Time-based view threshold", "properties": { "duration_seconds": { - "description": "Seconds of viewing required (e.g., 30 for YouTube-style '30 seconds = view')", + "description": "Seconds of viewing required", "minimum": 1, "type": "integer" } @@ -59,27 +64,46 @@ ], "type": "object" }, + "price_guidance": { + "description": "Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "properties": { + "p25": { + "description": "25th percentile of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p50": { + "description": "Median of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p75": { + "description": "75th percentile of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p90": { + "description": "90th percentile of recent winning bids", + "minimum": 0, + "type": "number" + } + }, + "type": "object" + }, "pricing_model": { "const": "cpv", "description": "Cost per view at threshold", "type": "string" }, "pricing_option_id": { - "description": "Unique identifier for this pricing option within the product (e.g., 'cpv_usd_50pct')", + "description": "Unique identifier for this pricing option within the product", "type": "string" - }, - "rate": { - "description": "Fixed CPV rate (cost per view)", - "minimum": 0, - "type": "number" } }, "required": [ "pricing_option_id", "pricing_model", - "rate", "currency", - "is_fixed", "parameters" ], "title": "CPV Pricing Option", diff --git a/schemas/cache/pricing-options/flat-rate-option.json b/schemas/cache/pricing-options/flat-rate-option.json index a532550c..e54c06be 100644 --- a/schemas/cache/pricing-options/flat-rate-option.json +++ b/schemas/cache/pricing-options/flat-rate-option.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, - "description": "Flat rate pricing for DOOH, sponsorships, and time-based campaigns - fixed cost regardless of delivery volume", + "description": "Flat rate pricing for DOOH, sponsorships, and time-based campaigns. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", "properties": { "currency": { "description": "ISO 4217 currency code", @@ -14,10 +14,15 @@ "pattern": "^[A-Z]{3}$", "type": "string" }, - "is_fixed": { - "const": true, - "description": "Whether this is a fixed rate (true) or auction-based (false)", - "type": "boolean" + "fixed_price": { + "description": "Flat rate cost. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0, + "type": "number" + }, + "floor_price": { + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0, + "type": "number" }, "min_spend_per_package": { "description": "Minimum spend requirement per package using this pricing option, in the specified currency", @@ -29,63 +34,82 @@ "description": "Flat rate parameters for DOOH and time-based campaigns", "properties": { "daypart": { - "description": "Specific daypart for time-based pricing (e.g., 'morning_commute', 'evening_prime', 'overnight')", + "description": "Specific daypart for time-based pricing", "type": "string" }, "duration_hours": { - "description": "Duration in hours for time-based flat rate pricing (DOOH)", + "description": "Duration in hours for time-based pricing", "minimum": 0, "type": "number" }, "estimated_impressions": { - "description": "Estimated impressions for this flat rate option (informational, commonly used with SOV or time-based DOOH)", + "description": "Estimated impressions (informational)", "minimum": 0, "type": "integer" }, "loop_duration_seconds": { - "description": "Duration of ad loop rotation in seconds (DOOH)", + "description": "Duration of ad loop rotation in seconds", "minimum": 1, "type": "integer" }, "min_plays_per_hour": { - "description": "Minimum number of times ad plays per hour (DOOH frequency guarantee)", + "description": "Minimum plays per hour", "minimum": 0, "type": "integer" }, "sov_percentage": { - "description": "Guaranteed share of voice as percentage (DOOH, 0-100)", + "description": "Guaranteed share of voice (0-100)", "maximum": 100, "minimum": 0, "type": "number" }, "venue_package": { - "description": "Named venue package identifier for DOOH (e.g., 'times_square_network', 'airport_terminals')", + "description": "Named venue package identifier", "type": "string" } }, "type": "object" }, + "price_guidance": { + "description": "Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "properties": { + "p25": { + "description": "25th percentile of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p50": { + "description": "Median of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p75": { + "description": "75th percentile of recent winning bids", + "minimum": 0, + "type": "number" + }, + "p90": { + "description": "90th percentile of recent winning bids", + "minimum": 0, + "type": "number" + } + }, + "type": "object" + }, "pricing_model": { "const": "flat_rate", "description": "Fixed cost regardless of delivery volume", "type": "string" }, "pricing_option_id": { - "description": "Unique identifier for this pricing option within the product (e.g., 'flat_rate_usd_24h_takeover')", + "description": "Unique identifier for this pricing option within the product", "type": "string" - }, - "rate": { - "description": "Flat rate cost", - "minimum": 0, - "type": "number" } }, "required": [ "pricing_option_id", "pricing_model", - "currency", - "is_fixed", - "rate" + "currency" ], "title": "Flat Rate Pricing Option", "type": "object" diff --git a/schemas/cache/pricing-options/vcpm-fixed-option.json b/schemas/cache/pricing-options/vcpm-fixed-option.json deleted file mode 100644 index b811c932..00000000 --- a/schemas/cache/pricing-options/vcpm-fixed-option.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": true, - "description": "Viewable Cost Per Mille (cost per 1,000 viewable impressions) with guaranteed fixed rate - impressions meeting MRC viewability standard (50% pixels in-view for 1 second for display, 2 seconds for video)", - "properties": { - "currency": { - "description": "ISO 4217 currency code", - "examples": [ - "USD", - "EUR", - "GBP", - "JPY" - ], - "pattern": "^[A-Z]{3}$", - "type": "string" - }, - "is_fixed": { - "const": true, - "description": "Whether this is a fixed rate (true) or auction-based (false)", - "type": "boolean" - }, - "min_spend_per_package": { - "description": "Minimum spend requirement per package using this pricing option, in the specified currency", - "minimum": 0, - "type": "number" - }, - "pricing_model": { - "const": "vcpm", - "description": "Cost per 1,000 viewable impressions (MRC standard)", - "type": "string" - }, - "pricing_option_id": { - "description": "Unique identifier for this pricing option within the product (e.g., 'vcpm_usd_guaranteed')", - "type": "string" - }, - "rate": { - "description": "Fixed vCPM rate (cost per 1,000 viewable impressions)", - "minimum": 0, - "type": "number" - } - }, - "required": [ - "pricing_option_id", - "pricing_model", - "rate", - "currency", - "is_fixed" - ], - "title": "vCPM Fixed Rate Pricing Option", - "type": "object" -} \ No newline at end of file diff --git a/schemas/cache/pricing-options/vcpm-auction-option.json b/schemas/cache/pricing-options/vcpm-option.json similarity index 68% rename from schemas/cache/pricing-options/vcpm-auction-option.json rename to schemas/cache/pricing-options/vcpm-option.json index c2f03350..de523850 100644 --- a/schemas/cache/pricing-options/vcpm-auction-option.json +++ b/schemas/cache/pricing-options/vcpm-option.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, - "description": "Viewable Cost Per Mille (cost per 1,000 viewable impressions) with auction-based pricing - impressions meeting MRC viewability standard (50% pixels in-view for 1 second for display, 2 seconds for video)", + "description": "Viewable Cost Per Mille (cost per 1,000 viewable impressions) pricing - MRC viewability standard. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", "properties": { "currency": { "description": "ISO 4217 currency code", @@ -14,10 +14,15 @@ "pattern": "^[A-Z]{3}$", "type": "string" }, - "is_fixed": { - "const": false, - "description": "Whether this is a fixed rate (true) or auction-based (false)", - "type": "boolean" + "fixed_price": { + "description": "Fixed price per unit. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0, + "type": "number" + }, + "floor_price": { + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0, + "type": "number" }, "min_spend_per_package": { "description": "Minimum spend requirement per package using this pricing option, in the specified currency", @@ -25,13 +30,8 @@ "type": "number" }, "price_guidance": { - "description": "Statistical guidance for auction pricing", + "description": "Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", "properties": { - "floor": { - "description": "Minimum acceptable bid price", - "minimum": 0, - "type": "number" - }, "p25": { "description": "25th percentile of recent winning bids", "minimum": 0, @@ -53,9 +53,6 @@ "type": "number" } }, - "required": [ - "floor" - ], "type": "object" }, "pricing_model": { @@ -64,17 +61,15 @@ "type": "string" }, "pricing_option_id": { - "description": "Unique identifier for this pricing option within the product (e.g., 'vcpm_usd_auction')", + "description": "Unique identifier for this pricing option within the product", "type": "string" } }, "required": [ "pricing_option_id", "pricing_model", - "currency", - "price_guidance", - "is_fixed" + "currency" ], - "title": "vCPM Auction Pricing Option", + "title": "vCPM Pricing Option", "type": "object" } \ No newline at end of file diff --git a/src/adcp/__init__.py b/src/adcp/__init__.py index 785b880d..666249f3 100644 --- a/src/adcp/__init__.py +++ b/src/adcp/__init__.py @@ -67,11 +67,10 @@ # Creative Operations BuildCreativeRequest, BuildCreativeResponse, - # Pricing options (all 9 types for product creation) + # Pricing options (all types for product creation) CpcPricingOption, CpcvPricingOption, - CpmAuctionPricingOption, - CpmFixedRatePricingOption, + CpmPricingOption, CppPricingOption, CpvPricingOption, # Media Buy Operations @@ -121,8 +120,7 @@ SyncCreativesResponse, UpdateMediaBuyRequest, UpdateMediaBuyResponse, - VcpmAuctionPricingOption, - VcpmFixedRatePricingOption, + VcpmPricingOption, aliases, ) @@ -289,14 +287,12 @@ def get_adcp_version() -> str: # Pricing-related types "CpcPricingOption", "CpcvPricingOption", - "CpmAuctionPricingOption", - "CpmFixedRatePricingOption", + "CpmPricingOption", "CppPricingOption", "CpvPricingOption", "FlatRatePricingOption", "PriceGuidance", - "VcpmAuctionPricingOption", - "VcpmFixedRatePricingOption", + "VcpmPricingOption", # Configuration types "PushNotificationConfig", # Adagents validation diff --git a/src/adcp/types/__init__.py b/src/adcp/types/__init__.py index de330806..447683b1 100644 --- a/src/adcp/types/__init__.py +++ b/src/adcp/types/__init__.py @@ -69,8 +69,7 @@ Country, CpcPricingOption, CpcvPricingOption, - CpmAuctionPricingOption, - CpmFixedRatePricingOption, + CpmPricingOption, CppPricingOption, CpvPricingOption, CreateContentStandardsRequest, @@ -102,7 +101,6 @@ DimensionUnit, Disclaimer, DoohMetrics, - Embedding, Error, FeedbackSource, FeedFormat, @@ -253,8 +251,7 @@ ValidationMode, VastTrackingEvent, VastVersion, - VcpmAuctionPricingOption, - VcpmFixedRatePricingOption, + VcpmPricingOption, VenueBreakdownItem, VideoAsset, ViewThreshold, @@ -452,7 +449,6 @@ "DeliveryMetrics", "Disclaimer", "DoohMetrics", - "Embedding", "Error", "FeedFormat", "Fonts", @@ -498,14 +494,12 @@ # Pricing types "CpcPricingOption", "CpcvPricingOption", - "CpmAuctionPricingOption", - "CpmFixedRatePricingOption", + "CpmPricingOption", "CppPricingOption", "CpvPricingOption", "FlatRatePricingOption", "PriceGuidance", - "VcpmAuctionPricingOption", - "VcpmFixedRatePricingOption", + "VcpmPricingOption", # Status enums & simple types "SignalCatalogType", "Country", diff --git a/src/adcp/types/_ergonomic.py b/src/adcp/types/_ergonomic.py index 08cb1cdd..70a487f8 100644 --- a/src/adcp/types/_ergonomic.py +++ b/src/adcp/types/_ergonomic.py @@ -39,6 +39,7 @@ coerce_to_enum_list, coerce_to_model, ) + from adcp.types.generated_poc.core.context import ContextObject from adcp.types.generated_poc.core.creative_asset import CreativeAsset from adcp.types.generated_poc.core.creative_assignment import CreativeAssignment @@ -55,6 +56,20 @@ from adcp.types.generated_poc.media_buy.create_media_buy_request import ( CreateMediaBuyRequest, ) +from adcp.types.generated_poc.media_buy.get_products_request import GetProductsRequest +from adcp.types.generated_poc.media_buy.list_creative_formats_request import ( + ListCreativeFormatsRequest, +) +from adcp.types.generated_poc.media_buy.list_creatives_request import ( + FieldModel, + ListCreativesRequest, + Sort, +) +from adcp.types.generated_poc.media_buy.package_request import PackageRequest +from adcp.types.generated_poc.media_buy.package_update import ( + PackageUpdate1, + PackageUpdate2, +) from adcp.types.generated_poc.media_buy.create_media_buy_response import ( CreateMediaBuyResponse1, ) @@ -63,29 +78,15 @@ MediaBuyDelivery, NotificationType, ) -from adcp.types.generated_poc.media_buy.get_products_request import GetProductsRequest from adcp.types.generated_poc.media_buy.get_products_response import GetProductsResponse -from adcp.types.generated_poc.media_buy.list_creative_formats_request import ( - ListCreativeFormatsRequest, -) from adcp.types.generated_poc.media_buy.list_creative_formats_response import ( CreativeAgent, ListCreativeFormatsResponse, ) -from adcp.types.generated_poc.media_buy.list_creatives_request import ( - FieldModel, - ListCreativesRequest, - Sort, -) from adcp.types.generated_poc.media_buy.list_creatives_response import ( Creative, ListCreativesResponse, ) -from adcp.types.generated_poc.media_buy.package_request import PackageRequest -from adcp.types.generated_poc.media_buy.package_update import ( - PackageUpdate1, - PackageUpdate2, -) def _apply_coercion() -> None: diff --git a/src/adcp/types/_generated.py b/src/adcp/types/_generated.py index 28417334..27fc860c 100644 --- a/src/adcp/types/_generated.py +++ b/src/adcp/types/_generated.py @@ -10,7 +10,7 @@ DO NOT EDIT MANUALLY. Generated from: https://github.com/adcontextprotocol/adcp/tree/main/schemas -Generation date: 2026-01-25 21:17:54 UTC +Generation date: 2026-01-26 11:40:01 UTC """ # ruff: noqa: E501, I001 @@ -110,7 +110,6 @@ UpdateContentStandardsRequest, ) from adcp.types.generated_poc.content_standards.update_content_standards_response import ( - Error, UpdateContentStandardsResponse, ) from adcp.types.generated_poc.content_standards.validate_content_delivery_request import ( @@ -170,6 +169,7 @@ ) from adcp.types.generated_poc.core.deployment import Deployment, Deployment1, Deployment2 from adcp.types.generated_poc.core.destination import Destination, Destination1, Destination2 +from adcp.types.generated_poc.core.error import Error from adcp.types.generated_poc.core.ext import ExtensionObject from adcp.types.generated_poc.core.format import ( Asset2, @@ -278,13 +278,7 @@ Results, Results1, ) -from adcp.types.generated_poc.creative.preview_render import ( - Embedding, - PreviewRender, - PreviewRender1, - PreviewRender2, - PreviewRender3, -) +from adcp.types.generated_poc.creative.preview_render import PreviewRender from adcp.types.generated_poc.enums.adcp_domain import AdcpDomain from adcp.types.generated_poc.enums.asset_content_type import AssetContentType from adcp.types.generated_poc.enums.auth_scheme import AuthenticationScheme @@ -462,13 +456,9 @@ UpdateMediaBuyResponse1, UpdateMediaBuyResponse2, ) -from adcp.types.generated_poc.pricing_options.cpc_option import CpcPricingOption +from adcp.types.generated_poc.pricing_options.cpc_option import CpcPricingOption, PriceGuidance from adcp.types.generated_poc.pricing_options.cpcv_option import CpcvPricingOption -from adcp.types.generated_poc.pricing_options.cpm_auction_option import ( - CpmAuctionPricingOption, - PriceGuidance, -) -from adcp.types.generated_poc.pricing_options.cpm_fixed_option import CpmFixedRatePricingOption +from adcp.types.generated_poc.pricing_options.cpm_option import CpmPricingOption from adcp.types.generated_poc.pricing_options.cpp_option import CppPricingOption, Parameters from adcp.types.generated_poc.pricing_options.cpv_option import ( CpvPricingOption, @@ -476,8 +466,7 @@ ViewThreshold1, ) from adcp.types.generated_poc.pricing_options.flat_rate_option import FlatRatePricingOption -from adcp.types.generated_poc.pricing_options.vcpm_auction_option import VcpmAuctionPricingOption -from adcp.types.generated_poc.pricing_options.vcpm_fixed_option import VcpmFixedRatePricingOption +from adcp.types.generated_poc.pricing_options.vcpm_option import VcpmPricingOption from adcp.types.generated_poc.property.base_property_source import ( BasePropertySource, BasePropertySource1, @@ -702,8 +691,7 @@ "Coverage", "CpcPricingOption", "CpcvPricingOption", - "CpmAuctionPricingOption", - "CpmFixedRatePricingOption", + "CpmPricingOption", "CppPricingOption", "CpvPricingOption", "CreateContentStandardsRequest", @@ -757,7 +745,6 @@ "Dimensions1", "Disclaimer", "DoohMetrics", - "Embedding", "Endpoint", "Error", "Execution", @@ -885,9 +872,6 @@ "PreviewCreativeResponse2", "PreviewOutputFormat", "PreviewRender", - "PreviewRender1", - "PreviewRender2", - "PreviewRender3", "Price", "PriceGuidance", "Pricing", @@ -1041,8 +1025,7 @@ "VastAsset2", "VastTrackingEvent", "VastVersion", - "VcpmAuctionPricingOption", - "VcpmFixedRatePricingOption", + "VcpmPricingOption", "VenueBreakdownItem", "Verdict", "Video", diff --git a/src/adcp/types/aliases.py b/src/adcp/types/aliases.py index e28b5b31..aa6f14e9 100644 --- a/src/adcp/types/aliases.py +++ b/src/adcp/types/aliases.py @@ -61,10 +61,8 @@ # Preview creative responses PreviewCreativeResponse1, PreviewCreativeResponse2, - # Preview renders - PreviewRender1, - PreviewRender2, - PreviewRender3, + # Preview renders (single type after schema consolidation) + PreviewRender, # Publisher properties types PropertyId, PropertyTag, @@ -212,15 +210,16 @@ def process_result(result: SyncCreativeResult) -> None: PreviewCreativeInteractiveResponse = PreviewCreativeResponse2 """Preview response with interactive renders (iframe embedding).""" -# Preview Render Variants (discriminated by output_format) -UrlPreviewRender = PreviewRender1 -"""Preview render with output_format='url' - provides preview_url for iframe embedding.""" +# Preview Render Aliases (schema consolidated to single type) +# These aliases are kept for backwards compatibility but all point to the same type. +UrlPreviewRender = PreviewRender +"""Preview render with preview_url for iframe embedding.""" -HtmlPreviewRender = PreviewRender2 -"""Preview render with output_format='html' - provides preview_html for direct embedding.""" +HtmlPreviewRender = PreviewRender +"""Preview render with preview_html for direct embedding.""" -BothPreviewRender = PreviewRender3 -"""Preview render with output_format='both' - provides both preview_url and preview_html.""" +BothPreviewRender = PreviewRender +"""Preview render with both preview_url and preview_html.""" # ============================================================================ # ASSET TYPE ALIASES - Delivery & Kind Discriminated Unions diff --git a/src/adcp/types/generated_poc/content_standards/update_content_standards_response.py b/src/adcp/types/generated_poc/content_standards/update_content_standards_response.py index bb9f0505..ed5808e2 100644 --- a/src/adcp/types/generated_poc/content_standards/update_content_standards_response.py +++ b/src/adcp/types/generated_poc/content_standards/update_content_standards_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/update_content_standards_response.json -# timestamp: 2026-01-25T21:17:54+00:00 +# timestamp: 2026-01-26T11:40:01+00:00 from __future__ import annotations @@ -10,16 +10,10 @@ from pydantic import ConfigDict, Field from ..core import context as context_1 +from ..core import error from ..core import ext as ext_1 -class Error(AdCPBaseModel): - code: Annotated[ - str, Field(description='Error code (e.g., STANDARDS_NOT_FOUND, SCOPE_CONFLICT)') - ] - message: Annotated[str, Field(description='Human-readable error message')] - - class UpdateContentStandardsResponse(AdCPBaseModel): model_config = ConfigDict( extra='allow', @@ -32,7 +26,7 @@ class UpdateContentStandardsResponse(AdCPBaseModel): ] = None context: context_1.ContextObject | None = None errors: Annotated[ - list[Error] | None, Field(description='Errors that occurred during the update') + list[error.Error] | None, Field(description='Errors that occurred during the update') ] = None ext: ext_1.ExtensionObject | None = None standards_id: Annotated[ diff --git a/src/adcp/types/generated_poc/core/pricing_option.py b/src/adcp/types/generated_poc/core/pricing_option.py index 400af6c0..f9bbb8f0 100644 --- a/src/adcp/types/generated_poc/core/pricing_option.py +++ b/src/adcp/types/generated_poc/core/pricing_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/pricing_option.json -# timestamp: 2026-01-25T21:17:54+00:00 +# timestamp: 2026-01-26T11:40:01+00:00 from __future__ import annotations @@ -11,22 +11,18 @@ from ..pricing_options import ( cpc_option, cpcv_option, - cpm_auction_option, - cpm_fixed_option, + cpm_option, cpp_option, cpv_option, flat_rate_option, - vcpm_auction_option, - vcpm_fixed_option, + vcpm_option, ) class PricingOption( RootModel[ - cpm_fixed_option.CpmFixedRatePricingOption - | cpm_auction_option.CpmAuctionPricingOption - | vcpm_fixed_option.VcpmFixedRatePricingOption - | vcpm_auction_option.VcpmAuctionPricingOption + cpm_option.CpmPricingOption + | vcpm_option.VcpmPricingOption | cpc_option.CpcPricingOption | cpcv_option.CpcvPricingOption | cpv_option.CpvPricingOption @@ -35,17 +31,15 @@ class PricingOption( ] ): root: Annotated[ - cpm_fixed_option.CpmFixedRatePricingOption - | cpm_auction_option.CpmAuctionPricingOption - | vcpm_fixed_option.VcpmFixedRatePricingOption - | vcpm_auction_option.VcpmAuctionPricingOption + cpm_option.CpmPricingOption + | vcpm_option.VcpmPricingOption | cpc_option.CpcPricingOption | cpcv_option.CpcvPricingOption | cpv_option.CpvPricingOption | cpp_option.CppPricingOption | flat_rate_option.FlatRatePricingOption, Field( - description='A pricing model option offered by a publisher for a product. Each pricing model has its own schema with model-specific requirements.', + description="A pricing model option offered by a publisher for a product. Discriminated by pricing_model field. If fixed_price is present, it's fixed pricing. If absent, it's auction-based (floor_price and price_guidance optional).", title='Pricing Option', ), ] diff --git a/src/adcp/types/generated_poc/core/product_filters.py b/src/adcp/types/generated_poc/core/product_filters.py index 441931b3..51e4a19a 100644 --- a/src/adcp/types/generated_poc/core/product_filters.py +++ b/src/adcp/types/generated_poc/core/product_filters.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/product_filters.json -# timestamp: 2026-01-25T21:17:54+00:00 +# timestamp: 2026-01-26T11:40:01+00:00 from __future__ import annotations @@ -112,7 +112,10 @@ class ProductFilters(AdCPBaseModel): list[format_category.FormatCategory] | None, Field(description='Filter by format types') ] = None is_fixed_price: Annotated[ - bool | None, Field(description='Filter for fixed price vs auction products') + bool | None, + Field( + description='Filter by pricing availability: true = products offering fixed pricing (at least one option with fixed_price), false = products offering auction pricing (at least one option without fixed_price). Products with both fixed and auction options match both true and false.' + ), ] = None metros: Annotated[ list[Metro] | None, diff --git a/src/adcp/types/generated_poc/creative/preview_render.py b/src/adcp/types/generated_poc/creative/preview_render.py index 19e4247b..89935b13 100644 --- a/src/adcp/types/generated_poc/creative/preview_render.py +++ b/src/adcp/types/generated_poc/creative/preview_render.py @@ -1,144 +1,46 @@ # generated by datamodel-codegen: # filename: creative/preview_render.json -# timestamp: 2026-01-25T21:17:54+00:00 +# timestamp: 2026-01-26T11:40:01+00:00 from __future__ import annotations -from typing import Annotated, Literal +from typing import Annotated from adcp.types.base import AdCPBaseModel -from pydantic import AnyUrl, ConfigDict, Field, RootModel +from pydantic import AnyUrl, ConfigDict, Field class Dimensions(AdCPBaseModel): - height: Annotated[float, Field(ge=0.0)] - width: Annotated[float, Field(ge=0.0)] + width: Annotated[int, Field(description='Width in pixels', ge=1)] + height: Annotated[int, Field(description='Height in pixels', ge=1)] -class Embedding(AdCPBaseModel): - csp_policy: Annotated[ - str | None, Field(description='Content Security Policy requirements for embedding') - ] = None - recommended_sandbox: Annotated[ - str | None, - Field( - description="Recommended iframe sandbox attribute value (e.g., 'allow-scripts allow-same-origin')" - ), - ] = None - requires_https: Annotated[ - bool | None, Field(description='Whether this output requires HTTPS for secure embedding') - ] = None - supports_fullscreen: Annotated[ - bool | None, Field(description='Whether this output supports fullscreen mode') - ] = None - - -class PreviewRender1(AdCPBaseModel): +class PreviewRender(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) - dimensions: Annotated[ - Dimensions | None, Field(description='Dimensions for this rendered piece') - ] = None - embedding: Annotated[ - Embedding | None, - Field(description='Optional security and embedding metadata for safe iframe integration'), + render_id: Annotated[ + str | None, Field(description='Unique identifier for this render piece') ] = None - output_format: Annotated[ - Literal['url'], Field(description='Discriminator indicating preview_url is provided') - ] preview_url: Annotated[ AnyUrl, Field( - description='URL to an HTML page that renders this piece. Can be embedded in an iframe.' - ), - ] - render_id: Annotated[ - str, Field(description='Unique identifier for this rendered piece within the variant') - ] - role: Annotated[ - str, - Field( - description="Semantic role of this rendered piece. Use 'primary' for main content, 'companion' for associated banners, descriptive strings for device variants or custom roles." + description='URL to the rendered preview HTML page that can be embedded in an iframe' ), ] - - -class PreviewRender2(AdCPBaseModel): - model_config = ConfigDict( - extra='allow', - ) dimensions: Annotated[ - Dimensions | None, Field(description='Dimensions for this rendered piece') + Dimensions | None, Field(description='Dimensions of this render piece') ] = None - embedding: Annotated[ - Embedding | None, Field(description='Optional security and embedding metadata') - ] = None - output_format: Annotated[ - Literal['html'], Field(description='Discriminator indicating preview_html is provided') - ] - preview_html: Annotated[ - str, - Field( - description='Raw HTML for this rendered piece. Can be embedded directly in the page without iframe. Security warning: Only use with trusted creative agents as this bypasses iframe sandboxing.' - ), - ] - render_id: Annotated[ - str, Field(description='Unique identifier for this rendered piece within the variant') - ] - role: Annotated[ - str, + placement_hint: Annotated[ + str | None, Field( - description="Semantic role of this rendered piece. Use 'primary' for main content, 'companion' for associated banners, descriptive strings for device variants or custom roles." + description="Optional hint about where this piece should be placed (e.g., 'main', 'companion', 'banner')" ), - ] - - -class PreviewRender3(AdCPBaseModel): - model_config = ConfigDict( - extra='allow', - ) - dimensions: Annotated[ - Dimensions | None, Field(description='Dimensions for this rendered piece') ] = None - embedding: Annotated[ - Embedding | None, - Field(description='Optional security and embedding metadata for safe iframe integration'), - ] = None - output_format: Annotated[ - Literal['both'], - Field( - description='Discriminator indicating both preview_url and preview_html are provided' - ), - ] - preview_html: Annotated[ - str, - Field( - description='Raw HTML for this rendered piece. Can be embedded directly in the page without iframe. Security warning: Only use with trusted creative agents as this bypasses iframe sandboxing.' - ), - ] - preview_url: Annotated[ - AnyUrl, - Field( - description='URL to an HTML page that renders this piece. Can be embedded in an iframe.' - ), - ] - render_id: Annotated[ - str, Field(description='Unique identifier for this rendered piece within the variant') - ] - role: Annotated[ - str, - Field( - description="Semantic role of this rendered piece. Use 'primary' for main content, 'companion' for associated banners, descriptive strings for device variants or custom roles." - ), - ] - - -class PreviewRender(RootModel[PreviewRender1 | PreviewRender2 | PreviewRender3]): - root: Annotated[ - PreviewRender1 | PreviewRender2 | PreviewRender3, + media_type: Annotated[ + str | None, Field( - description='A single rendered piece of a creative preview with discriminated output format', - title='Preview Render', + description='MIME type of the preview content', + examples=['text/html', 'image/png', 'video/mp4'], ), - ] + ] = None diff --git a/src/adcp/types/generated_poc/pricing_options/cpc_option.py b/src/adcp/types/generated_poc/pricing_options/cpc_option.py index 1aa3537a..19aeef2a 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpc_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpc_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpc_option.json -# timestamp: 2026-01-25T21:17:54+00:00 +# timestamp: 2026-01-26T11:40:01+00:00 from __future__ import annotations @@ -10,6 +10,19 @@ from pydantic import ConfigDict, Field +class PriceGuidance(AdCPBaseModel): + p25: Annotated[ + float | None, Field(description='25th percentile of recent winning bids', ge=0.0) + ] = None + p50: Annotated[float | None, Field(description='Median of recent winning bids', ge=0.0)] = None + p75: Annotated[ + float | None, Field(description='75th percentile of recent winning bids', ge=0.0) + ] = None + p90: Annotated[ + float | None, Field(description='90th percentile of recent winning bids', ge=0.0) + ] = None + + class CpcPricingOption(AdCPBaseModel): model_config = ConfigDict( extra='allow', @@ -22,10 +35,20 @@ class CpcPricingOption(AdCPBaseModel): pattern='^[A-Z]{3}$', ), ] - is_fixed: Annotated[ - Literal[True], - Field(description='Whether this is a fixed rate (true) or auction-based (false)'), - ] + fixed_price: Annotated[ + float | None, + Field( + description='Fixed price per click. If present, this is fixed pricing. If absent, auction-based.', + ge=0.0, + ), + ] = None + floor_price: Annotated[ + float | None, + Field( + description='Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.', + ge=0.0, + ), + ] = None min_spend_per_package: Annotated[ float | None, Field( @@ -33,11 +56,13 @@ class CpcPricingOption(AdCPBaseModel): ge=0.0, ), ] = None - pricing_model: Annotated[Literal['cpc'], Field(description='Cost per click')] - pricing_option_id: Annotated[ - str, + price_guidance: Annotated[ + PriceGuidance | None, Field( - description="Unique identifier for this pricing option within the product (e.g., 'cpc_usd_fixed')" + description='Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.' ), + ] = None + pricing_model: Annotated[Literal['cpc'], Field(description='Cost per click')] + pricing_option_id: Annotated[ + str, Field(description='Unique identifier for this pricing option within the product') ] - rate: Annotated[float, Field(description='Fixed CPC rate (cost per click)', ge=0.0)] diff --git a/src/adcp/types/generated_poc/pricing_options/cpcv_option.py b/src/adcp/types/generated_poc/pricing_options/cpcv_option.py index d76f4b53..7f32800e 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpcv_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpcv_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpcv_option.json -# timestamp: 2026-01-25T21:17:54+00:00 +# timestamp: 2026-01-26T11:40:01+00:00 from __future__ import annotations @@ -10,6 +10,19 @@ from pydantic import ConfigDict, Field +class PriceGuidance(AdCPBaseModel): + p25: Annotated[ + float | None, Field(description='25th percentile of recent winning bids', ge=0.0) + ] = None + p50: Annotated[float | None, Field(description='Median of recent winning bids', ge=0.0)] = None + p75: Annotated[ + float | None, Field(description='75th percentile of recent winning bids', ge=0.0) + ] = None + p90: Annotated[ + float | None, Field(description='90th percentile of recent winning bids', ge=0.0) + ] = None + + class CpcvPricingOption(AdCPBaseModel): model_config = ConfigDict( extra='allow', @@ -22,10 +35,20 @@ class CpcvPricingOption(AdCPBaseModel): pattern='^[A-Z]{3}$', ), ] - is_fixed: Annotated[ - Literal[True], - Field(description='Whether this is a fixed rate (true) or auction-based (false)'), - ] + fixed_price: Annotated[ + float | None, + Field( + description='Fixed price per completed view. If present, this is fixed pricing. If absent, auction-based.', + ge=0.0, + ), + ] = None + floor_price: Annotated[ + float | None, + Field( + description='Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.', + ge=0.0, + ), + ] = None min_spend_per_package: Annotated[ float | None, Field( @@ -33,13 +56,15 @@ class CpcvPricingOption(AdCPBaseModel): ge=0.0, ), ] = None + price_guidance: Annotated[ + PriceGuidance | None, + Field( + description='Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.' + ), + ] = None pricing_model: Annotated[ Literal['cpcv'], Field(description='Cost per completed view (100% completion)') ] pricing_option_id: Annotated[ - str, - Field( - description="Unique identifier for this pricing option within the product (e.g., 'cpcv_usd_guaranteed')" - ), + str, Field(description='Unique identifier for this pricing option within the product') ] - rate: Annotated[float, Field(description='Fixed CPCV rate (cost per 100% completion)', ge=0.0)] diff --git a/src/adcp/types/generated_poc/pricing_options/cpm_fixed_option.py b/src/adcp/types/generated_poc/pricing_options/cpm_fixed_option.py deleted file mode 100644 index a11ef7ee..00000000 --- a/src/adcp/types/generated_poc/pricing_options/cpm_fixed_option.py +++ /dev/null @@ -1,43 +0,0 @@ -# generated by datamodel-codegen: -# filename: pricing_options/cpm_fixed_option.json -# timestamp: 2026-01-25T21:17:54+00:00 - -from __future__ import annotations - -from typing import Annotated, Literal - -from adcp.types.base import AdCPBaseModel -from pydantic import ConfigDict, Field - - -class CpmFixedRatePricingOption(AdCPBaseModel): - model_config = ConfigDict( - extra='allow', - ) - currency: Annotated[ - str, - Field( - description='ISO 4217 currency code', - examples=['USD', 'EUR', 'GBP', 'JPY'], - pattern='^[A-Z]{3}$', - ), - ] - is_fixed: Annotated[ - Literal[True], - Field(description='Whether this is a fixed rate (true) or auction-based (false)'), - ] - min_spend_per_package: Annotated[ - float | None, - Field( - description='Minimum spend requirement per package using this pricing option, in the specified currency', - ge=0.0, - ), - ] = None - pricing_model: Annotated[Literal['cpm'], Field(description='Cost per 1,000 impressions')] - pricing_option_id: Annotated[ - str, - Field( - description="Unique identifier for this pricing option within the product (e.g., 'cpm_usd_guaranteed')" - ), - ] - rate: Annotated[float, Field(description='Fixed CPM rate (cost per 1,000 impressions)', ge=0.0)] diff --git a/src/adcp/types/generated_poc/pricing_options/cpm_auction_option.py b/src/adcp/types/generated_poc/pricing_options/cpm_option.py similarity index 61% rename from src/adcp/types/generated_poc/pricing_options/cpm_auction_option.py rename to src/adcp/types/generated_poc/pricing_options/cpm_option.py index 46bb081a..adf8b2a3 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpm_auction_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpm_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: -# filename: pricing_options/cpm_auction_option.json -# timestamp: 2026-01-25T21:17:54+00:00 +# filename: pricing_options/cpm_option.json +# timestamp: 2026-01-26T11:40:01+00:00 from __future__ import annotations @@ -11,19 +11,13 @@ class PriceGuidance(AdCPBaseModel): - floor: Annotated[ - float, - Field( - description='Minimum bid price - publisher will reject bids under this value', ge=0.0 - ), - ] p25: Annotated[float | None, Field(description='25th percentile winning price', ge=0.0)] = None p50: Annotated[float | None, Field(description='Median winning price', ge=0.0)] = None p75: Annotated[float | None, Field(description='75th percentile winning price', ge=0.0)] = None p90: Annotated[float | None, Field(description='90th percentile winning price', ge=0.0)] = None -class CpmAuctionPricingOption(AdCPBaseModel): +class CpmPricingOption(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @@ -35,10 +29,20 @@ class CpmAuctionPricingOption(AdCPBaseModel): pattern='^[A-Z]{3}$', ), ] - is_fixed: Annotated[ - Literal[False], - Field(description='Whether this is a fixed rate (true) or auction-based (false)'), - ] + fixed_price: Annotated[ + float | None, + Field( + description='Fixed price per unit. If present, this is fixed pricing. If absent, auction-based.', + ge=0.0, + ), + ] = None + floor_price: Annotated[ + float | None, + Field( + description='Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.', + ge=0.0, + ), + ] = None min_spend_per_package: Annotated[ float | None, Field( @@ -47,12 +51,12 @@ class CpmAuctionPricingOption(AdCPBaseModel): ), ] = None price_guidance: Annotated[ - PriceGuidance, Field(description='Pricing guidance for auction-based CPM bidding') - ] - pricing_model: Annotated[Literal['cpm'], Field(description='Cost per 1,000 impressions')] - pricing_option_id: Annotated[ - str, + PriceGuidance | None, Field( - description="Unique identifier for this pricing option within the product (e.g., 'cpm_usd_auction')" + description='Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.' ), + ] = None + pricing_model: Annotated[Literal['cpm'], Field(description='Cost per 1,000 impressions')] + pricing_option_id: Annotated[ + str, Field(description='Unique identifier for this pricing option within the product') ] diff --git a/src/adcp/types/generated_poc/pricing_options/cpp_option.py b/src/adcp/types/generated_poc/pricing_options/cpp_option.py index 93506f84..e8aabe92 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpp_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpp_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpp_option.json -# timestamp: 2026-01-25T21:17:54+00:00 +# timestamp: 2026-01-26T11:40:01+00:00 from __future__ import annotations @@ -17,13 +17,25 @@ class Parameters(AdCPBaseModel): demographic: Annotated[ str, Field( - description='Target demographic in Nielsen format: P/M/W/A/C + age range. Examples: P18-49 (Persons 18-49), M25-54 (Men 25-54), W35+ (Women 35+), A18-34 (Adults 18-34), C2-11 (Children 2-11)', + description='Target demographic in Nielsen format (P18-49, M25-54, W35+, etc.)', pattern='^[PMWAC][0-9]{2}(-[0-9]{2}|\\+)$', ), ] - min_points: Annotated[ - float | None, - Field(description='Minimum GRPs/TRPs required for this pricing option', ge=0.0), + min_points: Annotated[float | None, Field(description='Minimum GRPs/TRPs required', ge=0.0)] = ( + None + ) + + +class PriceGuidance(AdCPBaseModel): + p25: Annotated[ + float | None, Field(description='25th percentile of recent winning bids', ge=0.0) + ] = None + p50: Annotated[float | None, Field(description='Median of recent winning bids', ge=0.0)] = None + p75: Annotated[ + float | None, Field(description='75th percentile of recent winning bids', ge=0.0) + ] = None + p90: Annotated[ + float | None, Field(description='90th percentile of recent winning bids', ge=0.0) ] = None @@ -39,10 +51,20 @@ class CppPricingOption(AdCPBaseModel): pattern='^[A-Z]{3}$', ), ] - is_fixed: Annotated[ - Literal[True], - Field(description='Whether this is a fixed rate (true) or auction-based (false)'), - ] + fixed_price: Annotated[ + float | None, + Field( + description='Fixed price per rating point. If present, this is fixed pricing. If absent, auction-based.', + ge=0.0, + ), + ] = None + floor_price: Annotated[ + float | None, + Field( + description='Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.', + ge=0.0, + ), + ] = None min_spend_per_package: Annotated[ float | None, Field( @@ -51,14 +73,15 @@ class CppPricingOption(AdCPBaseModel): ), ] = None parameters: Annotated[ - Parameters, - Field(description='CPP-specific parameters for demographic targeting and GRP requirements'), + Parameters, Field(description='CPP-specific parameters for demographic targeting') ] - pricing_model: Annotated[Literal['cpp'], Field(description='Cost per Gross Rating Point')] - pricing_option_id: Annotated[ - str, + price_guidance: Annotated[ + PriceGuidance | None, Field( - description="Unique identifier for this pricing option within the product (e.g., 'cpp_usd_p18-49')" + description='Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.' ), + ] = None + pricing_model: Annotated[Literal['cpp'], Field(description='Cost per Gross Rating Point')] + pricing_option_id: Annotated[ + str, Field(description='Unique identifier for this pricing option within the product') ] - rate: Annotated[float, Field(description='Fixed CPP rate (cost per rating point)', ge=0.0)] diff --git a/src/adcp/types/generated_poc/pricing_options/cpv_option.py b/src/adcp/types/generated_poc/pricing_options/cpv_option.py index 189f40dd..dcb65f3c 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpv_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpv_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpv_option.json -# timestamp: 2026-01-25T21:17:54+00:00 +# timestamp: 2026-01-26T11:40:01+00:00 from __future__ import annotations @@ -14,7 +14,7 @@ class ViewThreshold(RootModel[float]): root: Annotated[ float, Field( - description='Percentage completion threshold for CPV pricing (0.0 to 1.0, e.g., 0.5 = 50% completion)', + description='Percentage completion threshold (0.0 to 1.0, e.g., 0.5 = 50%)', ge=0.0, le=1.0, ), @@ -25,13 +25,7 @@ class ViewThreshold1(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) - duration_seconds: Annotated[ - int, - Field( - description="Seconds of viewing required (e.g., 30 for YouTube-style '30 seconds = view')", - ge=1, - ), - ] + duration_seconds: Annotated[int, Field(description='Seconds of viewing required', ge=1)] class Parameters(AdCPBaseModel): @@ -41,6 +35,19 @@ class Parameters(AdCPBaseModel): view_threshold: ViewThreshold | ViewThreshold1 +class PriceGuidance(AdCPBaseModel): + p25: Annotated[ + float | None, Field(description='25th percentile of recent winning bids', ge=0.0) + ] = None + p50: Annotated[float | None, Field(description='Median of recent winning bids', ge=0.0)] = None + p75: Annotated[ + float | None, Field(description='75th percentile of recent winning bids', ge=0.0) + ] = None + p90: Annotated[ + float | None, Field(description='90th percentile of recent winning bids', ge=0.0) + ] = None + + class CpvPricingOption(AdCPBaseModel): model_config = ConfigDict( extra='allow', @@ -53,10 +60,20 @@ class CpvPricingOption(AdCPBaseModel): pattern='^[A-Z]{3}$', ), ] - is_fixed: Annotated[ - Literal[True], - Field(description='Whether this is a fixed rate (true) or auction-based (false)'), - ] + fixed_price: Annotated[ + float | None, + Field( + description='Fixed price per view. If present, this is fixed pricing. If absent, auction-based.', + ge=0.0, + ), + ] = None + floor_price: Annotated[ + float | None, + Field( + description='Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.', + ge=0.0, + ), + ] = None min_spend_per_package: Annotated[ float | None, Field( @@ -67,11 +84,13 @@ class CpvPricingOption(AdCPBaseModel): parameters: Annotated[ Parameters, Field(description='CPV-specific parameters defining the view threshold') ] - pricing_model: Annotated[Literal['cpv'], Field(description='Cost per view at threshold')] - pricing_option_id: Annotated[ - str, + price_guidance: Annotated[ + PriceGuidance | None, Field( - description="Unique identifier for this pricing option within the product (e.g., 'cpv_usd_50pct')" + description='Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.' ), + ] = None + pricing_model: Annotated[Literal['cpv'], Field(description='Cost per view at threshold')] + pricing_option_id: Annotated[ + str, Field(description='Unique identifier for this pricing option within the product') ] - rate: Annotated[float, Field(description='Fixed CPV rate (cost per view)', ge=0.0)] diff --git a/src/adcp/types/generated_poc/pricing_options/flat_rate_option.py b/src/adcp/types/generated_poc/pricing_options/flat_rate_option.py index d6eec0cd..b8c553b8 100644 --- a/src/adcp/types/generated_poc/pricing_options/flat_rate_option.py +++ b/src/adcp/types/generated_poc/pricing_options/flat_rate_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/flat_rate_option.json -# timestamp: 2026-01-25T21:17:54+00:00 +# timestamp: 2026-01-26T11:40:01+00:00 from __future__ import annotations @@ -14,43 +14,37 @@ class Parameters(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) - daypart: Annotated[ - str | None, - Field( - description="Specific daypart for time-based pricing (e.g., 'morning_commute', 'evening_prime', 'overnight')" - ), - ] = None + daypart: Annotated[str | None, Field(description='Specific daypart for time-based pricing')] = ( + None + ) duration_hours: Annotated[ - float | None, - Field(description='Duration in hours for time-based flat rate pricing (DOOH)', ge=0.0), + float | None, Field(description='Duration in hours for time-based pricing', ge=0.0) ] = None estimated_impressions: Annotated[ - int | None, - Field( - description='Estimated impressions for this flat rate option (informational, commonly used with SOV or time-based DOOH)', - ge=0, - ), + int | None, Field(description='Estimated impressions (informational)', ge=0) ] = None loop_duration_seconds: Annotated[ - int | None, Field(description='Duration of ad loop rotation in seconds (DOOH)', ge=1) - ] = None - min_plays_per_hour: Annotated[ - int | None, - Field( - description='Minimum number of times ad plays per hour (DOOH frequency guarantee)', ge=0 - ), + int | None, Field(description='Duration of ad loop rotation in seconds', ge=1) ] = None + min_plays_per_hour: Annotated[int | None, Field(description='Minimum plays per hour', ge=0)] = ( + None + ) sov_percentage: Annotated[ - float | None, - Field( - description='Guaranteed share of voice as percentage (DOOH, 0-100)', ge=0.0, le=100.0 - ), + float | None, Field(description='Guaranteed share of voice (0-100)', ge=0.0, le=100.0) ] = None - venue_package: Annotated[ - str | None, - Field( - description="Named venue package identifier for DOOH (e.g., 'times_square_network', 'airport_terminals')" - ), + venue_package: Annotated[str | None, Field(description='Named venue package identifier')] = None + + +class PriceGuidance(AdCPBaseModel): + p25: Annotated[ + float | None, Field(description='25th percentile of recent winning bids', ge=0.0) + ] = None + p50: Annotated[float | None, Field(description='Median of recent winning bids', ge=0.0)] = None + p75: Annotated[ + float | None, Field(description='75th percentile of recent winning bids', ge=0.0) + ] = None + p90: Annotated[ + float | None, Field(description='90th percentile of recent winning bids', ge=0.0) ] = None @@ -66,10 +60,20 @@ class FlatRatePricingOption(AdCPBaseModel): pattern='^[A-Z]{3}$', ), ] - is_fixed: Annotated[ - Literal[True], - Field(description='Whether this is a fixed rate (true) or auction-based (false)'), - ] + fixed_price: Annotated[ + float | None, + Field( + description='Flat rate cost. If present, this is fixed pricing. If absent, auction-based.', + ge=0.0, + ), + ] = None + floor_price: Annotated[ + float | None, + Field( + description='Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.', + ge=0.0, + ), + ] = None min_spend_per_package: Annotated[ float | None, Field( @@ -81,13 +85,15 @@ class FlatRatePricingOption(AdCPBaseModel): Parameters | None, Field(description='Flat rate parameters for DOOH and time-based campaigns'), ] = None + price_guidance: Annotated[ + PriceGuidance | None, + Field( + description='Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.' + ), + ] = None pricing_model: Annotated[ Literal['flat_rate'], Field(description='Fixed cost regardless of delivery volume') ] pricing_option_id: Annotated[ - str, - Field( - description="Unique identifier for this pricing option within the product (e.g., 'flat_rate_usd_24h_takeover')" - ), + str, Field(description='Unique identifier for this pricing option within the product') ] - rate: Annotated[float, Field(description='Flat rate cost', ge=0.0)] diff --git a/src/adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py b/src/adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py deleted file mode 100644 index 420116ce..00000000 --- a/src/adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py +++ /dev/null @@ -1,47 +0,0 @@ -# generated by datamodel-codegen: -# filename: pricing_options/vcpm_fixed_option.json -# timestamp: 2026-01-25T21:17:54+00:00 - -from __future__ import annotations - -from typing import Annotated, Literal - -from adcp.types.base import AdCPBaseModel -from pydantic import ConfigDict, Field - - -class VcpmFixedRatePricingOption(AdCPBaseModel): - model_config = ConfigDict( - extra='allow', - ) - currency: Annotated[ - str, - Field( - description='ISO 4217 currency code', - examples=['USD', 'EUR', 'GBP', 'JPY'], - pattern='^[A-Z]{3}$', - ), - ] - is_fixed: Annotated[ - Literal[True], - Field(description='Whether this is a fixed rate (true) or auction-based (false)'), - ] - min_spend_per_package: Annotated[ - float | None, - Field( - description='Minimum spend requirement per package using this pricing option, in the specified currency', - ge=0.0, - ), - ] = None - pricing_model: Annotated[ - Literal['vcpm'], Field(description='Cost per 1,000 viewable impressions (MRC standard)') - ] - pricing_option_id: Annotated[ - str, - Field( - description="Unique identifier for this pricing option within the product (e.g., 'vcpm_usd_guaranteed')" - ), - ] - rate: Annotated[ - float, Field(description='Fixed vCPM rate (cost per 1,000 viewable impressions)', ge=0.0) - ] diff --git a/src/adcp/types/generated_poc/pricing_options/vcpm_auction_option.py b/src/adcp/types/generated_poc/pricing_options/vcpm_option.py similarity index 61% rename from src/adcp/types/generated_poc/pricing_options/vcpm_auction_option.py rename to src/adcp/types/generated_poc/pricing_options/vcpm_option.py index d2c9be3c..703402b1 100644 --- a/src/adcp/types/generated_poc/pricing_options/vcpm_auction_option.py +++ b/src/adcp/types/generated_poc/pricing_options/vcpm_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: -# filename: pricing_options/vcpm_auction_option.json -# timestamp: 2026-01-25T21:17:54+00:00 +# filename: pricing_options/vcpm_option.json +# timestamp: 2026-01-26T11:40:01+00:00 from __future__ import annotations @@ -11,7 +11,6 @@ class PriceGuidance(AdCPBaseModel): - floor: Annotated[float, Field(description='Minimum acceptable bid price', ge=0.0)] p25: Annotated[ float | None, Field(description='25th percentile of recent winning bids', ge=0.0) ] = None @@ -24,7 +23,7 @@ class PriceGuidance(AdCPBaseModel): ] = None -class VcpmAuctionPricingOption(AdCPBaseModel): +class VcpmPricingOption(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @@ -36,10 +35,20 @@ class VcpmAuctionPricingOption(AdCPBaseModel): pattern='^[A-Z]{3}$', ), ] - is_fixed: Annotated[ - Literal[False], - Field(description='Whether this is a fixed rate (true) or auction-based (false)'), - ] + fixed_price: Annotated[ + float | None, + Field( + description='Fixed price per unit. If present, this is fixed pricing. If absent, auction-based.', + ge=0.0, + ), + ] = None + floor_price: Annotated[ + float | None, + Field( + description='Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.', + ge=0.0, + ), + ] = None min_spend_per_package: Annotated[ float | None, Field( @@ -48,14 +57,14 @@ class VcpmAuctionPricingOption(AdCPBaseModel): ), ] = None price_guidance: Annotated[ - PriceGuidance, Field(description='Statistical guidance for auction pricing') - ] + PriceGuidance | None, + Field( + description='Optional pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.' + ), + ] = None pricing_model: Annotated[ Literal['vcpm'], Field(description='Cost per 1,000 viewable impressions (MRC standard)') ] pricing_option_id: Annotated[ - str, - Field( - description="Unique identifier for this pricing option within the product (e.g., 'vcpm_usd_auction')" - ), + str, Field(description='Unique identifier for this pricing option within the product') ] diff --git a/src/adcp/utils/preview_cache.py b/src/adcp/utils/preview_cache.py index 168fd41d..df0547ff 100644 --- a/src/adcp/utils/preview_cache.py +++ b/src/adcp/utils/preview_cache.py @@ -87,8 +87,7 @@ async def get_preview_data_for_manifest( first_render = preview.renders[0] if preview.renders else None if first_render: - # PreviewRender is a RootModel, access attributes via .root - render = first_render.root + render = first_render has_url = hasattr(render, "preview_url") preview_url = str(render.preview_url) if has_url else None preview_data = { diff --git a/tests/test_discriminated_unions.py b/tests/test_discriminated_unions.py index 2addc7bf..3e66990f 100644 --- a/tests/test_discriminated_unions.py +++ b/tests/test_discriminated_unions.py @@ -520,67 +520,39 @@ def test_product_accepts_mixed_publisher_properties(self): assert mixed_props[1].selection_type == "by_tag" -class TestPreviewRenderDiscriminators: - """Test PreviewRender discriminator field values match semantic aliases.""" +class TestPreviewRenderUnifiedType: + """Test PreviewRender unified type after schema consolidation. - def test_url_preview_render_has_url_discriminator(self): - """UrlPreviewRender has output_format='url'.""" + Note: The old schema had separate UrlPreviewRender, HtmlPreviewRender, and BothPreviewRender + variants discriminated by output_format. The new schema consolidates these into a single + PreviewRender type where preview_url is the only required field. All aliases now point + to the same underlying type for backwards compatibility. + """ + + def test_preview_render_accepts_url_only(self): + """PreviewRender accepts preview_url as the only required field.""" render = UrlPreviewRender( - render_id="render_1", - role="primary", - output_format="url", preview_url="https://preview.example.com/creative", ) - assert render.output_format == "url" - assert hasattr(render, "preview_url") - assert not hasattr(render, "preview_html") - - def test_html_preview_render_has_html_discriminator(self): - """HtmlPreviewRender has output_format='html'.""" - render = HtmlPreviewRender( - render_id="render_1", - role="primary", - output_format="html", - preview_html="
Preview HTML
", - ) - assert render.output_format == "html" - assert hasattr(render, "preview_html") - assert not hasattr(render, "preview_url") + assert str(render.preview_url) == "https://preview.example.com/creative" - def test_both_preview_render_has_both_discriminator(self): - """BothPreviewRender has output_format='both'.""" + def test_preview_render_accepts_all_fields(self): + """PreviewRender accepts all optional fields.""" render = BothPreviewRender( render_id="render_1", - role="primary", - output_format="both", preview_url="https://preview.example.com/creative", - preview_html="
Preview HTML
", + placement_hint="main", + media_type="text/html", ) - assert render.output_format == "both" - assert hasattr(render, "preview_url") - assert hasattr(render, "preview_html") - - def test_url_preview_render_rejects_wrong_discriminator(self): - """UrlPreviewRender rejects output_format='html'.""" - with pytest.raises(ValidationError) as exc_info: - UrlPreviewRender( - render_id="render_1", - role="primary", - output_format="html", # Wrong discriminator value - preview_url="https://preview.example.com/creative", - ) - assert "output_format" in str(exc_info.value).lower() - - def test_html_preview_render_rejects_wrong_discriminator(self): - """HtmlPreviewRender rejects output_format='url'.""" - with pytest.raises(ValidationError) as exc_info: - HtmlPreviewRender( - render_id="render_1", - role="primary", - output_format="url", # Wrong discriminator value - preview_html="
Preview HTML
", - ) - assert "output_format" in str(exc_info.value).lower() + assert str(render.preview_url) == "https://preview.example.com/creative" + assert render.render_id == "render_1" + assert render.placement_hint == "main" + assert render.media_type == "text/html" + + def test_all_preview_render_aliases_are_same_type(self): + """All preview render aliases point to the same unified type.""" + assert UrlPreviewRender is HtmlPreviewRender + assert HtmlPreviewRender is BothPreviewRender class TestVastAssetDiscriminators: diff --git a/tests/test_preview_html.py b/tests/test_preview_html.py index 1498a188..8dbf27f8 100644 --- a/tests/test_preview_html.py +++ b/tests/test_preview_html.py @@ -100,9 +100,8 @@ async def test_preview_creative(): assert result.success assert result.data assert len(result.data.previews) == 1 - # PreviewRender is a RootModel, access attributes via .root assert ( - str(result.data.previews[0].renders[0].root.preview_url) + str(result.data.previews[0].renders[0].preview_url) == "https://preview.example.com/abc123" ) mock_call.assert_called_once() diff --git a/tests/test_public_api.py b/tests/test_public_api.py index 7d3a4a0a..b6f5f5e1 100644 --- a/tests/test_public_api.py +++ b/tests/test_public_api.py @@ -50,13 +50,11 @@ def test_pricing_option_types_are_exported(): pricing_types = [ "CpcPricingOption", "CpcvPricingOption", - "CpmAuctionPricingOption", - "CpmFixedRatePricingOption", + "CpmPricingOption", "CppPricingOption", "CpvPricingOption", "FlatRatePricingOption", - "VcpmAuctionPricingOption", - "VcpmFixedRatePricingOption", + "VcpmPricingOption", ] for type_name in pricing_types: @@ -167,21 +165,21 @@ def test_format_has_new_assets_field(): # Note: assets_required is deprecated and may be removed in future versions -def test_pricing_options_are_discriminated_by_is_fixed(): - """Pricing option types have is_fixed discriminator field.""" - from adcp import CpcPricingOption, CpmAuctionPricingOption, CpmFixedRatePricingOption +def test_pricing_options_have_required_fields(): + """Pricing option types have required fields for pricing.""" + from adcp import CpcPricingOption, CpmPricingOption - # Fixed-rate options should have is_fixed discriminator - fixed_types = [CpmFixedRatePricingOption, CpcPricingOption] - for pricing_type in fixed_types: + # All pricing options should have pricing_model and pricing_option_id + pricing_types = [CpmPricingOption, CpcPricingOption] + for pricing_type in pricing_types: name = pricing_type.__name__ - assert "is_fixed" in pricing_type.model_fields, f"{name} missing is_fixed discriminator" + assert "pricing_model" in pricing_type.model_fields, f"{name} missing pricing_model" + assert "pricing_option_id" in pricing_type.model_fields, f"{name} missing pricing_option_id" + assert "currency" in pricing_type.model_fields, f"{name} missing currency" - # Auction options should have is_fixed discriminator - auction_types = [CpmAuctionPricingOption] - for pricing_type in auction_types: - name = pricing_type.__name__ - assert "is_fixed" in pricing_type.model_fields, f"{name} missing is_fixed discriminator" + # CPM pricing option should support both fixed and auction pricing via optional fields + assert "fixed_price" in CpmPricingOption.model_fields, "CpmPricingOption missing fixed_price" + assert "floor_price" in CpmPricingOption.model_fields, "CpmPricingOption missing floor_price" def test_semantic_aliases_point_to_discriminated_variants(): @@ -193,23 +191,20 @@ def test_semantic_aliases_point_to_discriminated_variants(): UrlPreviewRender, ) - # URL preview render should accept url output format + # URL preview render accepts preview_url (now the only required field) url_render = UrlPreviewRender( render_id="r1", - role="primary", - output_format="url", preview_url="https://example.com/preview", + media_type="text/html", ) - assert url_render.output_format == "url" + assert str(url_render.preview_url) == "https://example.com/preview" - # HTML preview render should accept html output format + # HTML preview render is now same as URL (unified PreviewRender type) html_render = HtmlPreviewRender( render_id="r2", - role="primary", - output_format="html", - preview_html="
Test
", + preview_url="https://example.com/preview2", ) - assert html_render.output_format == "html" + assert str(html_render.preview_url) == "https://example.com/preview2" # Success response should accept success fields success = CreateMediaBuySuccessResponse( diff --git a/tests/test_type_aliases.py b/tests/test_type_aliases.py index f57fe21b..9e1eeb95 100644 --- a/tests/test_type_aliases.py +++ b/tests/test_type_aliases.py @@ -219,19 +219,17 @@ def test_discriminated_union_aliases_point_to_correct_types(): from adcp.types._generated import ( DaastAsset1, DaastAsset2, - PreviewRender1, - PreviewRender2, - PreviewRender3, + PreviewRender, SubAsset1, SubAsset2, VastAsset1, VastAsset2, ) - # Preview renders - assert UrlPreviewRender is PreviewRender1 - assert HtmlPreviewRender is PreviewRender2 - assert BothPreviewRender is PreviewRender3 + # Preview renders - now all point to the same unified type + assert UrlPreviewRender is PreviewRender + assert HtmlPreviewRender is PreviewRender + assert BothPreviewRender is PreviewRender # VAST assets assert UrlVastAsset is VastAsset1 diff --git a/tests/test_type_coercion.py b/tests/test_type_coercion.py index 20784b84..1b02dad3 100644 --- a/tests/test_type_coercion.py +++ b/tests/test_type_coercion.py @@ -537,7 +537,7 @@ def test_get_products_response_accepts_product_subclass(self): from pydantic import Field from adcp.types import ( - CpmFixedRatePricingOption, + CpmPricingOption, DeliveryType, FormatId, GetProductsResponse, @@ -559,11 +559,10 @@ class ExtendedProduct(Product): delivery_measurement=DeliveryMeasurement(provider="Test Provider"), format_ids=[FormatId(agent_url="https://example.com", id="banner-300x250")], pricing_options=[ - CpmFixedRatePricingOption( + CpmPricingOption( currency="USD", pricing_option_id="opt-1", - rate=5.0, - is_fixed=True, + fixed_price=5.0, pricing_model="cpm", ) ], From 2afad34cab896b713d5ae00af4edec98320e2374 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Mon, 26 Jan 2026 06:49:40 -0500 Subject: [PATCH 04/13] fix: resolve ruff import sorting error in _ergonomic.py Co-Authored-By: Claude Opus 4.5 --- src/adcp/types/_ergonomic.py | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/adcp/types/_ergonomic.py b/src/adcp/types/_ergonomic.py index 70a487f8..08cb1cdd 100644 --- a/src/adcp/types/_ergonomic.py +++ b/src/adcp/types/_ergonomic.py @@ -39,7 +39,6 @@ coerce_to_enum_list, coerce_to_model, ) - from adcp.types.generated_poc.core.context import ContextObject from adcp.types.generated_poc.core.creative_asset import CreativeAsset from adcp.types.generated_poc.core.creative_assignment import CreativeAssignment @@ -56,20 +55,6 @@ from adcp.types.generated_poc.media_buy.create_media_buy_request import ( CreateMediaBuyRequest, ) -from adcp.types.generated_poc.media_buy.get_products_request import GetProductsRequest -from adcp.types.generated_poc.media_buy.list_creative_formats_request import ( - ListCreativeFormatsRequest, -) -from adcp.types.generated_poc.media_buy.list_creatives_request import ( - FieldModel, - ListCreativesRequest, - Sort, -) -from adcp.types.generated_poc.media_buy.package_request import PackageRequest -from adcp.types.generated_poc.media_buy.package_update import ( - PackageUpdate1, - PackageUpdate2, -) from adcp.types.generated_poc.media_buy.create_media_buy_response import ( CreateMediaBuyResponse1, ) @@ -78,15 +63,29 @@ MediaBuyDelivery, NotificationType, ) +from adcp.types.generated_poc.media_buy.get_products_request import GetProductsRequest from adcp.types.generated_poc.media_buy.get_products_response import GetProductsResponse +from adcp.types.generated_poc.media_buy.list_creative_formats_request import ( + ListCreativeFormatsRequest, +) from adcp.types.generated_poc.media_buy.list_creative_formats_response import ( CreativeAgent, ListCreativeFormatsResponse, ) +from adcp.types.generated_poc.media_buy.list_creatives_request import ( + FieldModel, + ListCreativesRequest, + Sort, +) from adcp.types.generated_poc.media_buy.list_creatives_response import ( Creative, ListCreativesResponse, ) +from adcp.types.generated_poc.media_buy.package_request import PackageRequest +from adcp.types.generated_poc.media_buy.package_update import ( + PackageUpdate1, + PackageUpdate2, +) def _apply_coercion() -> None: From 263665f08cfe9f644155888ef83448cd38709d1b Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Mon, 26 Jan 2026 07:04:15 -0500 Subject: [PATCH 05/13] feat: sync schemas with upstream and fix type generation - Fix generate_types.py to convert absolute /schemas/latest/ $ref paths to relative paths for proper schema resolution - Sync all schemas from upstream (ADCP package 2.6) - PreviewRender is now a discriminated union by output_format: - PreviewRender1 (output_format='url') with preview_url - PreviewRender2 (output_format='html') with preview_html - PreviewRender3 (output_format='both') with both - Update aliases: UrlPreviewRender, HtmlPreviewRender, BothPreviewRender now point to their respective variant types - Fix preview_cache.py to access RootModel.root for PreviewRender - Update tests for discriminated union types This fixes the "Validate schemas are up-to-date" CI failure. Co-Authored-By: Claude Opus 4.5 --- schemas/cache/.hashes.json | 23 +- schemas/cache/adagents.json | 11 +- .../artifact-webhook-payload.json | 5 +- schemas/cache/content-standards/artifact.json | 5 +- .../calibrate-content-request.json | 3 +- .../calibrate-content-response.json | 3 +- .../content-standards/content-standards.json | 9 +- .../create-content-standards-request.json | 11 +- .../get-content-standards-request.json | 5 +- .../get-content-standards-response.json | 11 +- .../get-media-buy-artifacts-request.json | 5 +- .../list-content-standards-response.json | 13 +- .../update-content-standards-request.json | 11 +- .../update-content-standards-response.json | 7 +- .../validate-content-delivery-request.json | 7 +- .../validate-content-delivery-response.json | 11 +- schemas/cache/core/activation-key.json | 1 + schemas/cache/core/assets/audio-asset.json | 1 + schemas/cache/core/assets/css-asset.json | 1 + schemas/cache/core/assets/daast-asset.json | 9 +- schemas/cache/core/assets/html-asset.json | 1 + schemas/cache/core/assets/image-asset.json | 1 + .../cache/core/assets/javascript-asset.json | 3 +- schemas/cache/core/assets/text-asset.json | 1 + schemas/cache/core/assets/url-asset.json | 3 +- schemas/cache/core/assets/vast-asset.json | 9 +- schemas/cache/core/assets/video-asset.json | 1 + schemas/cache/core/assets/webhook-asset.json | 7 +- schemas/cache/core/async-response-data.json | 33 +-- schemas/cache/core/brand-manifest-ref.json | 3 +- schemas/cache/core/brand-manifest.json | 3 +- schemas/cache/core/context.json | 1 + schemas/cache/core/creative-asset.json | 27 +- schemas/cache/core/creative-assignment.json | 1 + schemas/cache/core/creative-filters.json | 3 +- schemas/cache/core/creative-manifest.json | 29 +- schemas/cache/core/creative-policy.json | 5 +- schemas/cache/core/delivery-metrics.json | 1 + schemas/cache/core/deployment.json | 5 +- schemas/cache/core/destination.json | 1 + schemas/cache/core/error.json | 1 + schemas/cache/core/ext.json | 1 + schemas/cache/core/format-id.json | 1 + schemas/cache/core/format.json | 21 +- schemas/cache/core/frequency-cap.json | 1 + schemas/cache/core/identifier.json | 3 +- schemas/cache/core/mcp-webhook-payload.json | 9 +- schemas/cache/core/measurement.json | 1 + schemas/cache/core/media-buy-features.json | 1 + schemas/cache/core/media-buy.json | 7 +- schemas/cache/core/offering.json | 3 +- schemas/cache/core/package.json | 11 +- schemas/cache/core/performance-feedback.json | 5 +- schemas/cache/core/placement.json | 3 +- schemas/cache/core/pricing-option.json | 15 +- schemas/cache/core/product-allocation.json | 3 +- schemas/cache/core/product-filters.json | 15 +- schemas/cache/core/product.json | 23 +- schemas/cache/core/promoted-offerings.json | 7 +- schemas/cache/core/promoted-products.json | 1 + schemas/cache/core/property-id.json | 1 + schemas/cache/core/property-list-ref.json | 1 + schemas/cache/core/property-tag.json | 1 + schemas/cache/core/property.json | 9 +- schemas/cache/core/proposal.json | 5 +- schemas/cache/core/protocol-envelope.json | 5 +- .../core/publisher-property-selector.json | 5 +- .../cache/core/push-notification-config.json | 3 +- .../cache/core/reporting-capabilities.json | 5 +- schemas/cache/core/reporting-webhook.json | 5 +- schemas/cache/core/response.json | 1 + schemas/cache/core/signal-filters.json | 3 +- schemas/cache/core/start-timing.json | 1 + schemas/cache/core/sub-asset.json | 1 + schemas/cache/core/targeting.json | 7 +- schemas/cache/creative/asset-types/index.json | 3 +- .../list-creative-formats-request.json | 7 +- .../list-creative-formats-response.json | 11 +- .../creative/preview-creative-request.json | 23 +- .../creative/preview-creative-response.json | 13 +- schemas/cache/creative/preview-render.json | 259 +++++++++++++++--- schemas/cache/enums/adcp-domain.json | 1 + schemas/cache/enums/asset-content-type.json | 1 + schemas/cache/enums/auth-scheme.json | 1 + schemas/cache/enums/available-metric.json | 1 + schemas/cache/enums/channels.json | 1 + .../cache/enums/co-branding-requirement.json | 1 + schemas/cache/enums/creative-action.json | 1 + .../enums/creative-agent-capability.json | 1 + schemas/cache/enums/creative-sort-field.json | 1 + schemas/cache/enums/creative-status.json | 1 + schemas/cache/enums/daast-tracking-event.json | 1 + schemas/cache/enums/daast-version.json | 1 + schemas/cache/enums/delivery-type.json | 1 + schemas/cache/enums/dimension-unit.json | 1 + schemas/cache/enums/feed-format.json | 1 + schemas/cache/enums/feedback-source.json | 1 + schemas/cache/enums/format-category.json | 1 + schemas/cache/enums/format-id-parameter.json | 1 + schemas/cache/enums/frequency-cap-scope.json | 1 + schemas/cache/enums/geo-level.json | 1 + schemas/cache/enums/history-entry-type.json | 1 + schemas/cache/enums/http-method.json | 1 + schemas/cache/enums/identifier-types.json | 1 + .../cache/enums/javascript-module-type.json | 1 + .../cache/enums/landing-page-requirement.json | 1 + schemas/cache/enums/markdown-flavor.json | 1 + schemas/cache/enums/media-buy-status.json | 1 + schemas/cache/enums/metric-type.json | 1 + schemas/cache/enums/metro-system.json | 1 + schemas/cache/enums/notification-type.json | 1 + schemas/cache/enums/pacing.json | 1 + .../cache/enums/preview-output-format.json | 1 + schemas/cache/enums/pricing-model.json | 1 + schemas/cache/enums/property-type.json | 1 + .../enums/publisher-identifier-types.json | 1 + schemas/cache/enums/reporting-frequency.json | 1 + schemas/cache/enums/signal-catalog-type.json | 1 + schemas/cache/enums/sort-direction.json | 1 + schemas/cache/enums/task-status.json | 1 + schemas/cache/enums/task-type.json | 1 + schemas/cache/enums/update-frequency.json | 1 + schemas/cache/enums/url-asset-type.json | 1 + schemas/cache/enums/validation-mode.json | 1 + schemas/cache/enums/vast-tracking-event.json | 1 + schemas/cache/enums/vast-version.json | 1 + .../cache/enums/webhook-response-type.json | 1 + .../cache/enums/webhook-security-method.json | 1 + schemas/cache/extensions/extension-meta.json | 6 + schemas/cache/extensions/index.json | 3 +- .../media-buy/build-creative-request.json | 9 +- .../media-buy/build-creative-response.json | 13 +- ...dia-buy-async-response-input-required.json | 7 +- ...te-media-buy-async-response-submitted.json | 5 +- ...eate-media-buy-async-response-working.json | 5 +- .../media-buy/create-media-buy-request.json | 15 +- .../media-buy/create-media-buy-response.json | 13 +- .../get-media-buy-delivery-request.json | 9 +- .../get-media-buy-delivery-response.json | 15 +- ...roducts-async-response-input-required.json | 7 +- ...get-products-async-response-submitted.json | 5 +- .../get-products-async-response-working.json | 5 +- .../cache/media-buy/get-products-request.json | 11 +- .../media-buy/get-products-response.json | 11 +- .../list-authorized-properties-request.json | 5 +- .../list-authorized-properties-response.json | 9 +- .../list-creative-formats-request.json | 11 +- .../list-creative-formats-response.json | 11 +- .../media-buy/list-creatives-request.json | 11 +- .../media-buy/list-creatives-response.json | 35 +-- schemas/cache/media-buy/package-request.json | 13 +- schemas/cache/media-buy/package-update.json | 11 +- .../provide-performance-feedback-request.json | 9 +- ...provide-performance-feedback-response.json | 11 +- ...eatives-async-response-input-required.json | 5 +- ...nc-creatives-async-response-submitted.json | 5 +- ...sync-creatives-async-response-working.json | 5 +- .../media-buy/sync-creatives-request.json | 11 +- .../media-buy/sync-creatives-response.json | 13 +- ...dia-buy-async-response-input-required.json | 5 +- ...te-media-buy-async-response-submitted.json | 5 +- ...date-media-buy-async-response-working.json | 5 +- .../media-buy/update-media-buy-request.json | 13 +- .../media-buy/update-media-buy-response.json | 13 +- .../cache/pricing-options/cpcv-option.json | 1 + schemas/cache/pricing-options/cpm-option.json | 1 + schemas/cache/pricing-options/cpp-option.json | 1 + schemas/cache/pricing-options/cpv-option.json | 1 + .../pricing-options/flat-rate-option.json | 1 + .../cache/pricing-options/vcpm-option.json | 1 + .../cache/property/base-property-source.json | 7 +- .../create-property-list-request.json | 11 +- .../create-property-list-response.json | 5 +- .../delete-property-list-request.json | 5 +- .../delete-property-list-response.json | 3 +- .../property/get-property-list-request.json | 5 +- .../property/get-property-list-response.json | 9 +- .../property/list-property-lists-request.json | 5 +- .../list-property-lists-response.json | 5 +- schemas/cache/property/property-error.json | 3 +- .../property/property-feature-definition.json | 3 +- schemas/cache/property/property-feature.json | 1 + .../property-list-changed-webhook.json | 3 +- .../cache/property/property-list-filters.json | 9 +- schemas/cache/property/property-list.json | 7 +- .../update-property-list-request.json | 11 +- .../update-property-list-response.json | 5 +- .../get-adcp-capabilities-request.json | 5 +- .../get-adcp-capabilities-response.json | 13 +- schemas/cache/protocols/adcp-extension.json | 1 + .../signals/activate-signal-request.json | 7 +- .../signals/activate-signal-response.json | 13 +- .../cache/signals/get-signals-request.json | 9 +- .../cache/signals/get-signals-response.json | 11 +- .../si-capabilities.json | 1 + .../si-get-offering-request.json | 3 +- .../si-get-offering-response.json | 5 +- .../sponsored-intelligence/si-identity.json | 1 + .../si-initiate-session-request.json | 7 +- .../si-initiate-session-response.json | 9 +- .../si-send-message-request.json | 3 +- .../si-send-message-response.json | 7 +- .../si-terminate-session-request.json | 3 +- .../si-terminate-session-response.json | 5 +- .../sponsored-intelligence/si-ui-element.json | 1 + scripts/generate_types.py | 39 ++- src/adcp/types/_ergonomic.py | 29 +- src/adcp/types/_generated.py | 14 +- src/adcp/types/aliases.py | 20 +- .../generated_poc/creative/preview_render.py | 134 +++++++-- .../extensions/extension_meta.py | 10 +- src/adcp/utils/preview_cache.py | 3 +- tests/test_discriminated_unions.py | 60 ++-- tests/test_preview_html.py | 7 +- tests/test_public_api.py | 15 +- tests/test_type_aliases.py | 12 +- 216 files changed, 1142 insertions(+), 591 deletions(-) diff --git a/schemas/cache/.hashes.json b/schemas/cache/.hashes.json index 01ea267a..fcf9ddf9 100644 --- a/schemas/cache/.hashes.json +++ b/schemas/cache/.hashes.json @@ -1,5 +1,5 @@ { - "https://adcontextprotocol.org/schemas/latest/index.json": "0f2b374b1a022b320c53e29871336ec18f1a892f22e817d536ce11b7c3140237", + "https://adcontextprotocol.org/schemas/latest/index.json": "434a613eba94b2f69b28823770e08501073b3c356e7f5a112e26c4fb9d0b29c0", "https://adcontextprotocol.org/schemas/latest/adagents.json": "585f06ed0f898c207531b208706d66fb2fe8c184355e8e332aa6dd14697cb537", "https://adcontextprotocol.org/schemas/latest/content-standards/artifact-webhook-payload.json": "a5ddff12ff1d6316636919bc87359980512e63ff688d4b742628ab06b91b537b", "https://adcontextprotocol.org/schemas/latest/content-standards/artifact.json": "b499571575b8e0f11b5c21dd32189fd19191d32a795cff225165fdfd0092917b", @@ -7,11 +7,9 @@ "https://adcontextprotocol.org/schemas/latest/content-standards/calibrate-content-response.json": "55b76ae2eb728abc8b5dd9d5d2f3af25a4dc6c31c06d8a76db5d4544e6001ecd", "https://adcontextprotocol.org/schemas/latest/content-standards/content-standards.json": "f6cc2b2cdb83494c7f11a15bc1e4118eecca4f6a9efa11abcd03660eba4bbd0e", "https://adcontextprotocol.org/schemas/latest/content-standards/create-content-standards-request.json": "025c2495689f85d209fba6191b74d070e0db58e913d355dc1e9cbf80dcc8ec72", - "https://adcontextprotocol.org/schemas/latest/content-standards/create-content-standards-response.json": "9c5cf7b12680c14ce13542d0c032f7b5135a0546a917147aac8633bd43618ec5", "https://adcontextprotocol.org/schemas/latest/content-standards/get-content-standards-request.json": "abe28cf4158bfa4f4333734639e62fd4d3057ab9fbc8eed0e121e51ac6962004", "https://adcontextprotocol.org/schemas/latest/content-standards/get-content-standards-response.json": "2b857288ce95461fd5e278fe27d6a21dbb06c442ee2a8f41db2530e547280991", "https://adcontextprotocol.org/schemas/latest/content-standards/get-media-buy-artifacts-request.json": "62866c85ca88dd674c89b9be02e875b599265875368802b6a8c7c8564bd4c607", - "https://adcontextprotocol.org/schemas/latest/content-standards/get-media-buy-artifacts-response.json": "bdac754a8fafed7152bbafc42bfa4abf2ed85b6e8feb5ac952be731748ecd751", "https://adcontextprotocol.org/schemas/latest/content-standards/list-content-standards-response.json": "9a1add4101da91e188e95a893ae50ec6c7eae6b3dc9cecb14c9edddf0a9a4c2b", "https://adcontextprotocol.org/schemas/latest/content-standards/update-content-standards-request.json": "b0b5ad96853c0f90870716ae855b2d683d168859cab32d1f67afed7e734c014a", "https://adcontextprotocol.org/schemas/latest/content-standards/update-content-standards-response.json": "68b2307f5a152df438f8b406873292947d477cd1d8e392a074ac5b7f61dfd190", @@ -63,6 +61,7 @@ "https://adcontextprotocol.org/schemas/latest/core/promoted-products.json": "8046efb31fb8e0c8c009123591a5446ee9db684f20f9d46c5f3f7e78492231b9", "https://adcontextprotocol.org/schemas/latest/core/property-id.json": "16ff353402c03691a7290a0f7578a901b63a0f7e83567b8903c5c6f89e1fb6f0", "https://adcontextprotocol.org/schemas/latest/core/property-list-ref.json": "50c908159f9d02bff2a3330ac1bdbe2a46c47649a3efbc0a8eb9f8118b3b70bc", + "https://adcontextprotocol.org/schemas/latest/core/property-tag.json": "6f2c35324ca6c5533a2c3d1a5837360c813a0905be68b11da7a46965ec37d59c", "https://adcontextprotocol.org/schemas/latest/core/property.json": "f81a2eefccc2ebf38db5c08a6aa99935fb03736a5abc946a4a4aa72a47015349", "https://adcontextprotocol.org/schemas/latest/core/proposal.json": "440619ed4ef8dfb877509ea2e383b130d22a0f3e5422916ddf8f51212fba7754", "https://adcontextprotocol.org/schemas/latest/core/protocol-envelope.json": "38fca1729f9a8cd242b5f081559f195b097bb3e0f36456a53af30d0c8212015c", @@ -75,11 +74,12 @@ "https://adcontextprotocol.org/schemas/latest/core/start-timing.json": "8e07e0469f434f3d3ba998e2b1fe58fc3dd097915e2d5e0c547cadfd5a469158", "https://adcontextprotocol.org/schemas/latest/core/sub-asset.json": "c0293416fd0275afd5ef59bd68675ff8ea37e4d4ba8f3a13e375711529a6399a", "https://adcontextprotocol.org/schemas/latest/core/targeting.json": "59224c362353602192d617a61bb66326c834e2cec09a138d90906d7f2241cd22", - "https://adcontextprotocol.org/schemas/latest/creative/asset-types/index.json": "9dc55de12aede8e02b24acc2e8f9e61a94365b897ab065f87896ed0ae5e6eb56", + "https://adcontextprotocol.org/schemas/latest/creative/asset-types/index.json": "c77e5886fd1c6bf2293aa144d782c43e9959cb76138b9e20e5568738cbd91fcc", "https://adcontextprotocol.org/schemas/latest/creative/list-creative-formats-request.json": "3997894b7d40e2ae95107e872dec2549f1b445cae0c606f77a4949825e1741d0", "https://adcontextprotocol.org/schemas/latest/creative/list-creative-formats-response.json": "160adbe2020191bd6ded0b094ea6a2e5ca9cb814f468e1bb70326ee59b7df1a3", "https://adcontextprotocol.org/schemas/latest/creative/preview-creative-request.json": "5f4f3095501e3fb1fd8f46815d963326a57b452c85b6c42ed4dc64cf8b928029", "https://adcontextprotocol.org/schemas/latest/creative/preview-creative-response.json": "caf1adb408cb6f9e07ab8eb33f683af118294f632cb39e1deaa8d92beb846056", + "https://adcontextprotocol.org/schemas/latest/creative/preview-render.json": "b4837c5a4027d7034f90ddf914c2e5e1a90e4ba6ee76f68a1b622e8a6cf64fc3", "https://adcontextprotocol.org/schemas/latest/enums/adcp-domain.json": "5f13f5da2b16c09e2b99ba8960356a03c92f6fb7758abe3ec33ff46050e78eba", "https://adcontextprotocol.org/schemas/latest/enums/asset-content-type.json": "74414bc886efb8a52794da63cfbb873befd9d24c87d9293ac88008bd496dfafc", "https://adcontextprotocol.org/schemas/latest/enums/auth-scheme.json": "492732201479760e022e7e20461874312403dab836af0f45c1382fd7b59c8b17", @@ -100,17 +100,19 @@ "https://adcontextprotocol.org/schemas/latest/enums/format-id-parameter.json": "0783749a5ac1e2eff4cc523eec16e3a723e107b3718bd55e1bc671cf230b0a1f", "https://adcontextprotocol.org/schemas/latest/enums/frequency-cap-scope.json": "3275a767cbde71235e7a23d0d775b5d58afb1859936393b04eb2c7c976ef2493", "https://adcontextprotocol.org/schemas/latest/enums/geo-level.json": "e6b65de7e6699c4171eba799553a39f8d3bdc787242ef7bfa269b6f6d77a1bfa", + "https://adcontextprotocol.org/schemas/latest/enums/history-entry-type.json": "e77c87be1493e84d83ffb567113303e2b50baa1dbd8c1ea791e2e8822f2bbf64", "https://adcontextprotocol.org/schemas/latest/enums/http-method.json": "75c12b6e8868b0248841bbf8e666fd097308276f59a2c8f809fa279a88c06188", "https://adcontextprotocol.org/schemas/latest/enums/identifier-types.json": "73190ea41c388af5b6b9c56358c4bce893b0f7cf61bc5062647f9987755451ed", "https://adcontextprotocol.org/schemas/latest/enums/javascript-module-type.json": "da4746acdce608ce9497f59e7fdbc97a649367e55aebe4b9675feb3176e8525e", "https://adcontextprotocol.org/schemas/latest/enums/landing-page-requirement.json": "5a09b76855c541b23ccf1aaa8ea87e77203d358b5c01c1b255722f21ac6327a4", "https://adcontextprotocol.org/schemas/latest/enums/markdown-flavor.json": "df8836754968fb1c02fc7725aa1bce56e315c4cec11515a19058b5d6a0cf782b", "https://adcontextprotocol.org/schemas/latest/enums/media-buy-status.json": "70bd2fca8832137c3b504c4b80934fdf8a57bcb45c4e1bf821fc49096aae53f9", + "https://adcontextprotocol.org/schemas/latest/enums/metric-type.json": "41eafcfaf6206670aabecd65abd5c1f2d0c4af019a3e4055d26aecfdccfd0a75", "https://adcontextprotocol.org/schemas/latest/enums/metro-system.json": "f8cde6b0bd45c4fbabef8ff90e01c57ffc8d5a821d7f50b94de48a6ed7cf1641", "https://adcontextprotocol.org/schemas/latest/enums/notification-type.json": "be6d4177c9350e8fdced52773b483acf464beecd567934cf020e53c43e61afac", "https://adcontextprotocol.org/schemas/latest/enums/pacing.json": "6fb8e62bfdc40bb48e0620ed71310f21a821fdfbe644c625d01b6a68ba4e40bb", - "https://adcontextprotocol.org/schemas/latest/enums/postal-system.json": "20651c3197e7554ced864c3addb71a27ac257952988e5248db8f6f882fad12d6", "https://adcontextprotocol.org/schemas/latest/enums/preview-output-format.json": "b14841f4e6689b3a3d2afa5740b4787ba49961d39ede2f9b92b709ad7970b32e", + "https://adcontextprotocol.org/schemas/latest/enums/pricing-model.json": "eb2aee267593d91e7f02ee0143fd8c2226021560fbee6b7ad983188f216f5f5a", "https://adcontextprotocol.org/schemas/latest/enums/property-type.json": "7e047eb116c41b4682818f89c8b19573636a546500289d48be189945318ded83", "https://adcontextprotocol.org/schemas/latest/enums/publisher-identifier-types.json": "3d4f8baf9ea57f525d1f126d58190588c17b05c7493ea2c9ff5737922cc96c4d", "https://adcontextprotocol.org/schemas/latest/enums/reporting-frequency.json": "b480016e39a0b8a4493e55f5bda13b153e8df7c4c07ee49586cd77bdfdab0af5", @@ -126,13 +128,14 @@ "https://adcontextprotocol.org/schemas/latest/enums/webhook-response-type.json": "72ba18db0a6fabd814195e895841e4cd6af5b54c4d6a954552c36284da5c4075", "https://adcontextprotocol.org/schemas/latest/enums/webhook-security-method.json": "80c1a7622b750af3bcfd2695569a3b348e42d5c8614378c27a65f8c7374e9165", "https://adcontextprotocol.org/schemas/latest/extensions/extension-meta.json": "639103027d657206b40a9bdfff0baded2588835e6f15e5b0f7acfec748e94423", - "https://adcontextprotocol.org/schemas/latest/extensions/index.json": "60db88edbb93cd31cd0d41b3f0dc31fc9b3afd6f9d39cc49fbb7226b50fe0687", + "https://adcontextprotocol.org/schemas/latest/extensions/index.json": "3ec78be3f30e7e6cb05758bea27e8ea44922356dfc026af86031536f7ee31f11", "https://adcontextprotocol.org/schemas/latest/media-buy/build-creative-request.json": "0eadf98c199f8b29475a600cd9bf6d71cd6adb135c4e2d65cf7a0ec8efb5f566", "https://adcontextprotocol.org/schemas/latest/media-buy/build-creative-response.json": "67c3e0d4b3f0c641e7e86833ab5e54c872d9cc79e673bf414abb412c81853973", "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-async-response-input-required.json": "397bb7a973f943bdb2c53b36822c93ecdc815d3e5184a1129cad8648d88f378a", "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-async-response-submitted.json": "7c9502344a561c3aca8752e6d95918444eb905b82413af0c6a8e4782963ce4f2", "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-async-response-working.json": "f8023b1dd59955843ecf2ee3c79a81ca83411ced35daa58a6e7210ad88678e00", "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-request.json": "b0fe4b12e80e79dc7269281e627ae0882ccd5d5b48520563209be24f359eac0d", + "https://adcontextprotocol.org/schemas/latest/media-buy/create-media-buy-response.json": "02e3fb22715890ede07cf7fa976b2d2025754b3cb88aa68be3c3479fdb7bbea5", "https://adcontextprotocol.org/schemas/latest/media-buy/get-media-buy-delivery-request.json": "4c2c5c3daeadec0dd8c5f3284cbd552905cf3987b10135ffb3bb87f05584c229", "https://adcontextprotocol.org/schemas/latest/media-buy/get-media-buy-delivery-response.json": "6abd494e57bd0f43ad5089bc438d116e9c74892791c3fbb9db669e859627457c", "https://adcontextprotocol.org/schemas/latest/media-buy/get-products-async-response-input-required.json": "107e27baf08f80a97a0de83a24faaf37cae5c0c3112ba707ff191af1c2ad4ea6", @@ -147,16 +150,19 @@ "https://adcontextprotocol.org/schemas/latest/media-buy/list-creatives-request.json": "d45bc1bdcc9dca066c2430992b30dd6c9b37ce667957bdc2d1048cbe250b7a4c", "https://adcontextprotocol.org/schemas/latest/media-buy/list-creatives-response.json": "9fe8f7628332bb3a4c6f146529b34a609cb210918bac7e058dd39835a007384f", "https://adcontextprotocol.org/schemas/latest/media-buy/package-request.json": "11d3ac74b3d07a2b16165f34cbebed8e688565115e45c722dedf1d0663f8d819", + "https://adcontextprotocol.org/schemas/latest/media-buy/package-update.json": "6cd7b8089cd0b3179ef66b161f9bdd6a42dd6007be7401bbc0a96bbd48337bee", "https://adcontextprotocol.org/schemas/latest/media-buy/provide-performance-feedback-request.json": "8fff8a6e58cf2f8dd95e2e1cb53ef1b3c2154991a577547a2f8c75028867a81b", "https://adcontextprotocol.org/schemas/latest/media-buy/provide-performance-feedback-response.json": "bebd13943d48ad8e8b419bd69f9fa2a9b4df30c379ae74219904e698231e7371", + "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-async-response-input-required.json": "62b4e86135542f4076b7bcf6edf157a7bb919e168ea97d0afb1ef1fe4ff2b8dd", "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-async-response-submitted.json": "0a6df44b4224a4b38d25673d0f813022e124c7ac0bcc7eccb95e673849af7368", "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-async-response-working.json": "5a336a8217d13fa112ac3dd1ed2d2c707f8abd9bb9ff05af674c22138dc24c90", "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-request.json": "01cfece0e07ba8825656aec890bd2e9293918d41695d777ca70d684f626d19d6", "https://adcontextprotocol.org/schemas/latest/media-buy/sync-creatives-response.json": "1fc6bf8348c520aaf2ec2041b64f50307de7edc30e54dc0de81e36af88e2833f", "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-async-response-input-required.json": "73ecee00cf0babc200778621b78148a54327df3436dedf349d83c734a99fc4e4", + "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-async-response-submitted.json": "d4736323140cf6db5522e1de5aeb1023f8a7b608d319ede26b86d28c57bea0ef", "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-async-response-working.json": "ccca3256ac3179a2125922718efde61367b9046bdfdee156bdaa72c1398f2ed3", "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-request.json": "11ab339a8e3dae8a5f0d9df0b680eb7acfe96c294922b5b1678e6e302c1f6b76", - "https://adcontextprotocol.org/schemas/latest/pricing-options/cpc-option.json": "a0c5d6d801932b92df96e422d20d7c19c9d678f741fa7f273e2d1d7ca297499f", + "https://adcontextprotocol.org/schemas/latest/media-buy/update-media-buy-response.json": "aca3e048a43704e0f7dee2370c4ad4c4b662805e4fe39b3dde7cfea3bba1101c", "https://adcontextprotocol.org/schemas/latest/pricing-options/cpcv-option.json": "d4533d055f304024097eca3988df2530e532f2b4a19e4cbda0d9d3555545c059", "https://adcontextprotocol.org/schemas/latest/pricing-options/cpm-option.json": "345bc9fa5cb3c5615da7fa1f02d29ff1c82e4464a55d523bb40d02db6af9427d", "https://adcontextprotocol.org/schemas/latest/pricing-options/cpp-option.json": "f670e68a8808ca3a2f596c71ab5fc917f774fb14e1c53affba7c01bed79a138f", @@ -168,7 +174,6 @@ "https://adcontextprotocol.org/schemas/latest/property/create-property-list-response.json": "b7ceada500f573191cd0ef9e07817cb35f5e1b2dc1180cb15a231db460ee1655", "https://adcontextprotocol.org/schemas/latest/property/delete-property-list-request.json": "5713450eb83436a1cf90a5636f6b54a1b0c5ffd1a15c481bca462000c4d05dd3", "https://adcontextprotocol.org/schemas/latest/property/delete-property-list-response.json": "222fff1b07bd9d20ce0a4db6a723ed7d86b9b34ea9e5139394c444275586c4e5", - "https://adcontextprotocol.org/schemas/latest/property/feature-requirement.json": "16e9f8f0f8a3e5150f264698be1ec1a68aba0999cf5d6c11ce26b2d0bc72bedb", "https://adcontextprotocol.org/schemas/latest/property/get-property-list-request.json": "99edd1056bd089fc32967b42f8e33dbb90b68e46ff8a2d9a627e5ec79aeb47ed", "https://adcontextprotocol.org/schemas/latest/property/get-property-list-response.json": "436570d44119ee309d53855e7ac82ee6ce002282502154c3f5187710848c9372", "https://adcontextprotocol.org/schemas/latest/property/list-property-lists-request.json": "cd3f516ea9ae6125e2aefbe3c4e99e8ba34c6fb904fb84e5d957ac00424f708d", @@ -194,7 +199,9 @@ "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-identity.json": "6b1fad0cb8433b15055b7e2a8271d7ee1ac405db6f5e19bb9aa8eb405a747797", "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-initiate-session-request.json": "dd872808799aa225cb7c5723d162aaa21c3265b84f26ebb13dd12b4b6076b26c", "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-initiate-session-response.json": "3eb8440b2be7b8d4777003b34f3094fd6d1c6b87a3236163d584192352b0c7f7", + "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-send-message-request.json": "b8a789094d4288cf277070e762f01bb22b3248c9730797603974891741bbc3a4", "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-send-message-response.json": "6c3e693333c009d37a45678ce73d9b3ee0bcb7ea3a4089187f0ab422dd04df97", "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-terminate-session-request.json": "8121c3cbf497bef6e5b265a3520daa8cb1c38cd133e8d593b4558f175f7fab95", + "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-terminate-session-response.json": "446b2ff92b8522d805af1592334d56c045e891608bc87f751007c8afe552d188", "https://adcontextprotocol.org/schemas/latest/sponsored-intelligence/si-ui-element.json": "e7d434246c38e1d047896cfdfec30ffda5f842ea8a4f699c5701c6c7c22bfaf8" } \ No newline at end of file diff --git a/schemas/cache/adagents.json b/schemas/cache/adagents.json index ab0ef5e7..1461f75b 100644 --- a/schemas/cache/adagents.json +++ b/schemas/cache/adagents.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/adagents.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Declaration of authorized sales agents for advertising inventory. Hosted at /.well-known/adagents.json on publisher domains. Can either contain the full structure inline or reference an authoritative URL.", "examples": [ @@ -351,7 +352,7 @@ "property_ids": { "description": "Property IDs this agent is authorized for. Resolved against the top-level properties array in this file", "items": { - "$ref": "core/property-id.json" + "$ref": "/schemas/latest/core/property-id.json" }, "minItems": 1, "type": "array" @@ -387,7 +388,7 @@ "property_tags": { "description": "Tags identifying which properties this agent is authorized for. Resolved against the top-level properties array in this file using tag matching", "items": { - "$ref": "core/property-tag.json" + "$ref": "/schemas/latest/core/property-tag.json" }, "minItems": 1, "type": "array" @@ -423,7 +424,7 @@ "properties": { "description": "Specific properties this agent is authorized for (alternative to property_ids/property_tags)", "items": { - "$ref": "core/property.json" + "$ref": "/schemas/latest/core/property.json" }, "minItems": 1, "type": "array" @@ -459,7 +460,7 @@ "publisher_properties": { "description": "Properties from other publisher domains this agent is authorized for. Each entry specifies a publisher domain and which of their properties this agent can sell", "items": { - "$ref": "core/publisher-property-selector.json" + "$ref": "/schemas/latest/core/publisher-property-selector.json" }, "minItems": 1, "type": "array" @@ -536,7 +537,7 @@ "properties": { "description": "Array of all properties covered by this adagents.json file. Defines the canonical property list that authorized agents reference.", "items": { - "$ref": "core/property.json" + "$ref": "/schemas/latest/core/property.json" }, "minItems": 1, "type": "array" diff --git a/schemas/cache/content-standards/artifact-webhook-payload.json b/schemas/cache/content-standards/artifact-webhook-payload.json index 5d672d24..aec7a3ee 100644 --- a/schemas/cache/content-standards/artifact-webhook-payload.json +++ b/schemas/cache/content-standards/artifact-webhook-payload.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/content-standards/artifact-webhook-payload.json", "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "description": "Payload sent by sales agents to orchestrators when pushing content artifacts for governance validation. Complements get_media_buy_artifacts for push-based artifact delivery.", @@ -8,7 +9,7 @@ "items": { "properties": { "artifact": { - "$ref": "artifact.json", + "$ref": "/schemas/latest/content-standards/artifact.json", "description": "The content artifact" }, "delivered_at": { @@ -38,7 +39,7 @@ "type": "string" }, "ext": { - "$ref": "../core/ext.json" + "$ref": "/schemas/latest/core/ext.json" }, "media_buy_id": { "description": "Media buy identifier these artifacts belong to", diff --git a/schemas/cache/content-standards/artifact.json b/schemas/cache/content-standards/artifact.json index 8ee92049..174dff84 100644 --- a/schemas/cache/content-standards/artifact.json +++ b/schemas/cache/content-standards/artifact.json @@ -65,6 +65,7 @@ "type": "object" } }, + "$id": "/schemas/latest/content-standards/artifact.json", "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "description": "Content artifact for safety and suitability evaluation. An artifact represents content adjacent to an ad placement - a news article, podcast segment, video chapter, or social post. Artifacts are collections of assets (text, images, video, audio) plus metadata and signals.", @@ -249,7 +250,7 @@ "type": "array" }, "format_id": { - "$ref": "../core/format-id.json", + "$ref": "/schemas/latest/core/format-id.json", "description": "Optional reference to a format definition. Uses the same format registry as creative formats." }, "identifiers": { @@ -323,7 +324,7 @@ "type": "object" }, "property_id": { - "$ref": "../core/identifier.json", + "$ref": "/schemas/latest/core/identifier.json", "description": "Identifier for the property where this artifact appears" }, "published_time": { diff --git a/schemas/cache/content-standards/calibrate-content-request.json b/schemas/cache/content-standards/calibrate-content-request.json index 7154faaf..92d293a8 100644 --- a/schemas/cache/content-standards/calibrate-content-request.json +++ b/schemas/cache/content-standards/calibrate-content-request.json @@ -1,9 +1,10 @@ { + "$id": "/schemas/latest/content-standards/calibrate-content-request.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Request parameters for evaluating content during calibration. Multi-turn dialogue is handled at the protocol layer via contextId.", "properties": { "artifact": { - "$ref": "artifact.json", + "$ref": "/schemas/latest/content-standards/artifact.json", "description": "Artifact to evaluate" }, "standards_id": { diff --git a/schemas/cache/content-standards/calibrate-content-response.json b/schemas/cache/content-standards/calibrate-content-response.json index a1a0f0be..196fe768 100644 --- a/schemas/cache/content-standards/calibrate-content-response.json +++ b/schemas/cache/content-standards/calibrate-content-response.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/content-standards/calibrate-content-response.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Response payload with verdict and detailed explanations for collaborative calibration", "oneOf": [ @@ -69,7 +70,7 @@ "properties": { "errors": { "items": { - "$ref": "../core/error.json" + "$ref": "/schemas/latest/core/error.json" }, "type": "array" }, diff --git a/schemas/cache/content-standards/content-standards.json b/schemas/cache/content-standards/content-standards.json index ac920a7f..ecbe89f1 100644 --- a/schemas/cache/content-standards/content-standards.json +++ b/schemas/cache/content-standards/content-standards.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/content-standards/content-standards.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "A content standards configuration defining brand safety and suitability policies. Standards are scoped by brand, geography, and channel. Multiple standards can be active simultaneously for different scopes.", "properties": { @@ -8,14 +9,14 @@ "fail": { "description": "Artifacts that fail the content standards", "items": { - "$ref": "artifact.json" + "$ref": "/schemas/latest/content-standards/artifact.json" }, "type": "array" }, "pass": { "description": "Artifacts that pass the content standards", "items": { - "$ref": "artifact.json" + "$ref": "/schemas/latest/content-standards/artifact.json" }, "type": "array" } @@ -25,7 +26,7 @@ "channels_any": { "description": "Advertising channels. Standards apply to ANY of the listed channels (OR logic).", "items": { - "$ref": "../enums/channels.json" + "$ref": "/schemas/latest/enums/channels.json" }, "type": "array" }, @@ -37,7 +38,7 @@ "type": "array" }, "ext": { - "$ref": "../core/ext.json" + "$ref": "/schemas/latest/core/ext.json" }, "languages_any": { "description": "BCP 47 language tags (e.g., 'en', 'de', 'fr'). Standards apply to content in ANY of these languages (OR logic). Content in unlisted languages is not covered by these standards.", diff --git a/schemas/cache/content-standards/create-content-standards-request.json b/schemas/cache/content-standards/create-content-standards-request.json index 1779d0db..727f9d76 100644 --- a/schemas/cache/content-standards/create-content-standards-request.json +++ b/schemas/cache/content-standards/create-content-standards-request.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/content-standards/create-content-standards-request.json", "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "description": "Request parameters for creating a new content standards configuration", @@ -35,7 +36,7 @@ "type": "object" }, { - "$ref": "artifact.json", + "$ref": "/schemas/latest/content-standards/artifact.json", "description": "Full artifact with pre-extracted content (text, images, video, audio)" } ] @@ -71,7 +72,7 @@ "type": "object" }, { - "$ref": "artifact.json", + "$ref": "/schemas/latest/content-standards/artifact.json", "description": "Full artifact with pre-extracted content (text, images, video, audio)" } ] @@ -82,10 +83,10 @@ "type": "object" }, "context": { - "$ref": "../core/context.json" + "$ref": "/schemas/latest/core/context.json" }, "ext": { - "$ref": "../core/ext.json" + "$ref": "/schemas/latest/core/ext.json" }, "policy": { "description": "Natural language policy describing acceptable and unacceptable content contexts. Used by LLMs and human reviewers to make judgments.", @@ -97,7 +98,7 @@ "channels_any": { "description": "Advertising channels. Standards apply to ANY of the listed channels (OR logic).", "items": { - "$ref": "../enums/channels.json" + "$ref": "/schemas/latest/enums/channels.json" }, "type": "array" }, diff --git a/schemas/cache/content-standards/get-content-standards-request.json b/schemas/cache/content-standards/get-content-standards-request.json index 4ee7f59e..d4f756d7 100644 --- a/schemas/cache/content-standards/get-content-standards-request.json +++ b/schemas/cache/content-standards/get-content-standards-request.json @@ -1,12 +1,13 @@ { + "$id": "/schemas/latest/content-standards/get-content-standards-request.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Request parameters for retrieving content safety policies", "properties": { "context": { - "$ref": "../core/context.json" + "$ref": "/schemas/latest/core/context.json" }, "ext": { - "$ref": "../core/ext.json" + "$ref": "/schemas/latest/core/ext.json" }, "standards_id": { "description": "Identifier for the standards configuration to retrieve", diff --git a/schemas/cache/content-standards/get-content-standards-response.json b/schemas/cache/content-standards/get-content-standards-response.json index 5aa29b9e..6b0caa3f 100644 --- a/schemas/cache/content-standards/get-content-standards-response.json +++ b/schemas/cache/content-standards/get-content-standards-response.json @@ -1,17 +1,18 @@ { + "$id": "/schemas/latest/content-standards/get-content-standards-response.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Response payload with content safety policies", "oneOf": [ { "allOf": [ { - "$ref": "content-standards.json" + "$ref": "/schemas/latest/content-standards/content-standards.json" } ], "description": "Success response - returns the content standards configuration", "properties": { "context": { - "$ref": "../core/context.json" + "$ref": "/schemas/latest/core/context.json" }, "errors": { "description": "Field must not be present in success response", @@ -24,16 +25,16 @@ "description": "Error response", "properties": { "context": { - "$ref": "../core/context.json" + "$ref": "/schemas/latest/core/context.json" }, "errors": { "items": { - "$ref": "../core/error.json" + "$ref": "/schemas/latest/core/error.json" }, "type": "array" }, "ext": { - "$ref": "../core/ext.json" + "$ref": "/schemas/latest/core/ext.json" }, "standards_id": { "description": "Field must not be present in error response", diff --git a/schemas/cache/content-standards/get-media-buy-artifacts-request.json b/schemas/cache/content-standards/get-media-buy-artifacts-request.json index 0ad47936..bbb598cd 100644 --- a/schemas/cache/content-standards/get-media-buy-artifacts-request.json +++ b/schemas/cache/content-standards/get-media-buy-artifacts-request.json @@ -1,16 +1,17 @@ { + "$id": "/schemas/latest/content-standards/get-media-buy-artifacts-request.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Request parameters for retrieving content artifacts from a media buy for validation", "properties": { "context": { - "$ref": "../core/context.json" + "$ref": "/schemas/latest/core/context.json" }, "cursor": { "description": "Pagination cursor for fetching subsequent pages", "type": "string" }, "ext": { - "$ref": "../core/ext.json" + "$ref": "/schemas/latest/core/ext.json" }, "limit": { "default": 1000, diff --git a/schemas/cache/content-standards/list-content-standards-response.json b/schemas/cache/content-standards/list-content-standards-response.json index e826e00d..88e6098c 100644 --- a/schemas/cache/content-standards/list-content-standards-response.json +++ b/schemas/cache/content-standards/list-content-standards-response.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/content-standards/list-content-standards-response.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Response payload with list of content standards configurations", "oneOf": [ @@ -6,19 +7,19 @@ "description": "Success response - returns array of content standards", "properties": { "context": { - "$ref": "../core/context.json" + "$ref": "/schemas/latest/core/context.json" }, "errors": { "description": "Field must not be present in success response", "not": {} }, "ext": { - "$ref": "../core/ext.json" + "$ref": "/schemas/latest/core/ext.json" }, "standards": { "description": "Array of content standards configurations matching the filter criteria", "items": { - "$ref": "content-standards.json" + "$ref": "/schemas/latest/content-standards/content-standards.json" }, "type": "array" } @@ -32,16 +33,16 @@ "description": "Error response", "properties": { "context": { - "$ref": "../core/context.json" + "$ref": "/schemas/latest/core/context.json" }, "errors": { "items": { - "$ref": "../core/error.json" + "$ref": "/schemas/latest/core/error.json" }, "type": "array" }, "ext": { - "$ref": "../core/ext.json" + "$ref": "/schemas/latest/core/ext.json" }, "standards": { "description": "Field must not be present in error response", diff --git a/schemas/cache/content-standards/update-content-standards-request.json b/schemas/cache/content-standards/update-content-standards-request.json index 91db59d5..2f59c8c6 100644 --- a/schemas/cache/content-standards/update-content-standards-request.json +++ b/schemas/cache/content-standards/update-content-standards-request.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/content-standards/update-content-standards-request.json", "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "description": "Request parameters for updating an existing content standards configuration. Creates a new version.", @@ -35,7 +36,7 @@ "type": "object" }, { - "$ref": "artifact.json", + "$ref": "/schemas/latest/content-standards/artifact.json", "description": "Full artifact with pre-extracted content (text, images, video, audio)" } ] @@ -71,7 +72,7 @@ "type": "object" }, { - "$ref": "artifact.json", + "$ref": "/schemas/latest/content-standards/artifact.json", "description": "Full artifact with pre-extracted content (text, images, video, audio)" } ] @@ -82,10 +83,10 @@ "type": "object" }, "context": { - "$ref": "../core/context.json" + "$ref": "/schemas/latest/core/context.json" }, "ext": { - "$ref": "../core/ext.json" + "$ref": "/schemas/latest/core/ext.json" }, "policy": { "description": "Updated natural language policy describing acceptable and unacceptable content contexts.", @@ -97,7 +98,7 @@ "channels_any": { "description": "Advertising channels. Standards apply to ANY of the listed channels (OR logic).", "items": { - "$ref": "../enums/channels.json" + "$ref": "/schemas/latest/enums/channels.json" }, "type": "array" }, diff --git a/schemas/cache/content-standards/update-content-standards-response.json b/schemas/cache/content-standards/update-content-standards-response.json index e160948a..03c2972e 100644 --- a/schemas/cache/content-standards/update-content-standards-response.json +++ b/schemas/cache/content-standards/update-content-standards-response.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/content-standards/update-content-standards-response.json", "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "description": "Response from updating a content standards configuration", @@ -8,17 +9,17 @@ "type": "string" }, "context": { - "$ref": "../core/context.json" + "$ref": "/schemas/latest/core/context.json" }, "errors": { "description": "Errors that occurred during the update", "items": { - "$ref": "../core/error.json" + "$ref": "/schemas/latest/core/error.json" }, "type": "array" }, "ext": { - "$ref": "../core/ext.json" + "$ref": "/schemas/latest/core/ext.json" }, "standards_id": { "description": "ID of the updated standards configuration", diff --git a/schemas/cache/content-standards/validate-content-delivery-request.json b/schemas/cache/content-standards/validate-content-delivery-request.json index 48d85355..88469bdf 100644 --- a/schemas/cache/content-standards/validate-content-delivery-request.json +++ b/schemas/cache/content-standards/validate-content-delivery-request.json @@ -1,12 +1,13 @@ { + "$id": "/schemas/latest/content-standards/validate-content-delivery-request.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Request parameters for batch validating delivery records against content safety policies", "properties": { "context": { - "$ref": "../core/context.json" + "$ref": "/schemas/latest/core/context.json" }, "ext": { - "$ref": "../core/ext.json" + "$ref": "/schemas/latest/core/ext.json" }, "feature_ids": { "description": "Specific features to evaluate (defaults to all)", @@ -25,7 +26,7 @@ "items": { "properties": { "artifact": { - "$ref": "artifact.json", + "$ref": "/schemas/latest/content-standards/artifact.json", "description": "Artifact where ad was delivered" }, "brand_context": { diff --git a/schemas/cache/content-standards/validate-content-delivery-response.json b/schemas/cache/content-standards/validate-content-delivery-response.json index 864b258a..6db2dac0 100644 --- a/schemas/cache/content-standards/validate-content-delivery-response.json +++ b/schemas/cache/content-standards/validate-content-delivery-response.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/content-standards/validate-content-delivery-response.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Response payload with per-record verdicts and optional feature breakdown", "oneOf": [ @@ -6,14 +7,14 @@ "description": "Success response", "properties": { "context": { - "$ref": "../core/context.json" + "$ref": "/schemas/latest/core/context.json" }, "errors": { "description": "Field must not be present in success response", "not": {} }, "ext": { - "$ref": "../core/ext.json" + "$ref": "/schemas/latest/core/ext.json" }, "results": { "description": "Per-record evaluation results", @@ -104,16 +105,16 @@ "description": "Error response", "properties": { "context": { - "$ref": "../core/context.json" + "$ref": "/schemas/latest/core/context.json" }, "errors": { "items": { - "$ref": "../core/error.json" + "$ref": "/schemas/latest/core/error.json" }, "type": "array" }, "ext": { - "$ref": "../core/ext.json" + "$ref": "/schemas/latest/core/ext.json" }, "summary": { "description": "Field must not be present in error response", diff --git a/schemas/cache/core/activation-key.json b/schemas/cache/core/activation-key.json index 6ad5331b..8e28f7f0 100644 --- a/schemas/cache/core/activation-key.json +++ b/schemas/cache/core/activation-key.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/core/activation-key.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Universal identifier for using a signal on a destination platform. Can be either a segment ID or a key-value pair depending on the platform's targeting mechanism.", "oneOf": [ diff --git a/schemas/cache/core/assets/audio-asset.json b/schemas/cache/core/assets/audio-asset.json index 4fd73b6f..5ed81f6c 100644 --- a/schemas/cache/core/assets/audio-asset.json +++ b/schemas/cache/core/assets/audio-asset.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/core/assets/audio-asset.json", "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "description": "Audio asset with URL and specifications", diff --git a/schemas/cache/core/assets/css-asset.json b/schemas/cache/core/assets/css-asset.json index 2327c516..7b120e71 100644 --- a/schemas/cache/core/assets/css-asset.json +++ b/schemas/cache/core/assets/css-asset.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/core/assets/css-asset.json", "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "description": "CSS stylesheet asset", diff --git a/schemas/cache/core/assets/daast-asset.json b/schemas/cache/core/assets/daast-asset.json index 6e25a751..3a8fe064 100644 --- a/schemas/cache/core/assets/daast-asset.json +++ b/schemas/cache/core/assets/daast-asset.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/core/assets/daast-asset.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", "oneOf": [ @@ -10,7 +11,7 @@ "type": "boolean" }, "daast_version": { - "$ref": "../../enums/daast-version.json", + "$ref": "/schemas/latest/enums/daast-version.json", "description": "DAAST specification version" }, "delivery_type": { @@ -26,7 +27,7 @@ "tracking_events": { "description": "Tracking events supported by this DAAST tag", "items": { - "$ref": "../../enums/daast-tracking-event.json" + "$ref": "/schemas/latest/enums/daast-tracking-event.json" }, "type": "array" }, @@ -54,7 +55,7 @@ "type": "string" }, "daast_version": { - "$ref": "../../enums/daast-version.json", + "$ref": "/schemas/latest/enums/daast-version.json", "description": "DAAST specification version" }, "delivery_type": { @@ -70,7 +71,7 @@ "tracking_events": { "description": "Tracking events supported by this DAAST tag", "items": { - "$ref": "../../enums/daast-tracking-event.json" + "$ref": "/schemas/latest/enums/daast-tracking-event.json" }, "type": "array" } diff --git a/schemas/cache/core/assets/html-asset.json b/schemas/cache/core/assets/html-asset.json index 0442fa79..efcff441 100644 --- a/schemas/cache/core/assets/html-asset.json +++ b/schemas/cache/core/assets/html-asset.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/core/assets/html-asset.json", "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "description": "HTML content asset", diff --git a/schemas/cache/core/assets/image-asset.json b/schemas/cache/core/assets/image-asset.json index 68aa14df..b8d60457 100644 --- a/schemas/cache/core/assets/image-asset.json +++ b/schemas/cache/core/assets/image-asset.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/core/assets/image-asset.json", "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "description": "Image asset with URL and dimensions", diff --git a/schemas/cache/core/assets/javascript-asset.json b/schemas/cache/core/assets/javascript-asset.json index a43cd804..87308706 100644 --- a/schemas/cache/core/assets/javascript-asset.json +++ b/schemas/cache/core/assets/javascript-asset.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/core/assets/javascript-asset.json", "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "description": "JavaScript code asset", @@ -8,7 +9,7 @@ "type": "string" }, "module_type": { - "$ref": "../../enums/javascript-module-type.json", + "$ref": "/schemas/latest/enums/javascript-module-type.json", "description": "JavaScript module type" } }, diff --git a/schemas/cache/core/assets/text-asset.json b/schemas/cache/core/assets/text-asset.json index 7f4b2d40..0cb69abe 100644 --- a/schemas/cache/core/assets/text-asset.json +++ b/schemas/cache/core/assets/text-asset.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/core/assets/text-asset.json", "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "description": "Text content asset", diff --git a/schemas/cache/core/assets/url-asset.json b/schemas/cache/core/assets/url-asset.json index ac5ea5bb..4e8d2c63 100644 --- a/schemas/cache/core/assets/url-asset.json +++ b/schemas/cache/core/assets/url-asset.json @@ -1,4 +1,5 @@ { + "$id": "/schemas/latest/core/assets/url-asset.json", "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "description": "URL reference asset", @@ -13,7 +14,7 @@ "type": "string" }, "url_type": { - "$ref": "../../enums/url-asset-type.json", + "$ref": "/schemas/latest/enums/url-asset-type.json", "description": "Type of URL asset: 'clickthrough' for user click destination (landing page), 'tracker_pixel' for impression/event tracking via HTTP request (fires GET, expects pixel/204 response), 'tracker_script' for measurement SDKs that must load as