From a4bd6d85bb7ab8799096d58c2f37414f7f7c995f Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Wed, 22 Apr 2026 00:32:55 -0400 Subject: [PATCH] feat(types): regenerate schemas + inject Literal-discriminator defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream spec added a cluster of breaking changes — most Asset classes went from 'discriminator is implicit' to 'asset_type is required'. Pydantic honors 'required' literally, breaking ergonomic construction: # Before upstream change: TextContent(content='hello') # After upstream change, pre-fix: TextContent(asset_type='text', content='hello') # must repeat tag Fix: inject_literal_discriminator_defaults() in post_generate_fixes.py. Pattern-matches AnnAssign nodes whose annotation is Literal['x'] (bare or Annotated-wrapped) with no default, appends ` = 'x'` on the same line. Touched 687 fields across 615 classes in 105 files — Asset types, pricing options, webhook types, catalog types, all spec discriminator fields. Wire consumption unchanged. Literal type still rejects other values, so validation strength preserved. Wire dicts with the tag present validate as before; dicts without the tag now also work (fall through to default) — useful for minimal clients. Pattern-based, not value-specific: robust to spec-value churn as long as the single-value-Literal discriminator shape holds. Also pulls upstream PRs #250 (design doc) and #251 (A2A contextId, +22 integration tests). All green. +16 new tests in tests/test_literal_discriminator_defaults.py. Covers Asset defaults, VAST/DAAST dual-discriminator defaults, validation- strength preservation, wire-format compatibility, injector meta-tests (skips multi-value literals, extracts single-value, skips non-Literal). 2102 passing (was 2086), mypy clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../calibrate-content-request.json | 2 +- .../calibrate-content-response.json | 2 +- .../create-content-standards-request.json | 2 +- .../create-content-standards-response.json | 2 +- .../get-content-standards-request.json | 2 +- .../get-content-standards-response.json | 2 +- .../get-media-buy-artifacts-request.json | 2 +- .../get-media-buy-artifacts-response.json | 2 +- .../list-content-standards-request.json | 2 +- .../list-content-standards-response.json | 2 +- .../update-content-standards-request.json | 2 +- .../update-content-standards-response.json | 2 +- .../validate-content-delivery-request.json | 2 +- .../validate-content-delivery-response.json | 2 +- .../cache/bundled/core/tasks-get-request.json | 2 +- .../bundled/core/tasks-get-response.json | 2 +- .../bundled/core/tasks-list-request.json | 2 +- .../bundled/core/tasks-list-response.json | 2 +- .../get-creative-delivery-request.json | 2 +- .../get-creative-delivery-response.json | 2159 +++----- .../get-creative-features-request.json | 2159 +++----- .../get-creative-features-response.json | 2 +- .../list-creative-formats-request.json | 2 +- .../list-creative-formats-response.json | 2 +- .../creative/list-creatives-request.json | 2 +- .../creative/list-creatives-response.json | 2163 +++----- .../creative/preview-creative-request.json | 4862 +++++++---------- .../creative/preview-creative-response.json | 2231 +++----- .../creative/sync-creatives-request.json | 2164 +++----- .../creative/sync-creatives-response.json | 2 +- .../media-buy/build-creative-request.json | 2159 +++----- .../media-buy/build-creative-response.json | 4772 ++++++---------- .../media-buy/create-media-buy-request.json | 2159 +++----- .../media-buy/create-media-buy-response.json | 2 +- .../get-media-buy-delivery-request.json | 2 +- .../get-media-buy-delivery-response.json | 2 +- .../media-buy/get-media-buys-request.json | 2 +- .../media-buy/get-media-buys-response.json | 2 +- .../media-buy/get-products-request.json | 21 +- .../media-buy/get-products-response.json | 122 +- .../list-creative-formats-request.json | 2 +- .../list-creative-formats-response.json | 2 +- .../bundled/media-buy/log-event-request.json | 2 +- .../bundled/media-buy/log-event-response.json | 2 +- .../bundled/media-buy/package-request.json | 2159 +++----- .../provide-performance-feedback-request.json | 2 +- ...provide-performance-feedback-response.json | 2 +- .../media-buy/sync-audiences-request.json | 2 +- .../media-buy/sync-audiences-response.json | 2 +- .../media-buy/sync-catalogs-request.json | 2 +- .../media-buy/sync-catalogs-response.json | 2 +- .../media-buy/sync-event-sources-request.json | 2 +- .../sync-event-sources-response.json | 2 +- .../media-buy/update-media-buy-request.json | 4488 ++++++--------- .../media-buy/update-media-buy-response.json | 2 +- .../create-property-list-request.json | 2 +- .../create-property-list-response.json | 2 +- .../delete-property-list-request.json | 2 +- .../delete-property-list-response.json | 2 +- .../property/get-property-list-request.json | 2 +- .../property/get-property-list-response.json | 2 +- .../property/list-property-lists-request.json | 2 +- .../list-property-lists-response.json | 2 +- .../update-property-list-request.json | 2 +- .../update-property-list-response.json | 2 +- .../validate-property-delivery-request.json | 2 +- .../validate-property-delivery-response.json | 2 +- .../get-adcp-capabilities-request.json | 2 +- .../get-adcp-capabilities-response.json | 2 +- .../signals/activate-signal-request.json | 2 +- .../signals/activate-signal-response.json | 2 +- .../bundled/signals/get-signals-request.json | 2 +- .../bundled/signals/get-signals-response.json | 2 +- .../si-get-offering-request.json | 12 +- .../si-get-offering-response.json | 2 +- .../si-initiate-session-request.json | 14 +- .../si-initiate-session-response.json | 2 +- .../si-send-message-request.json | 2 +- .../si-send-message-response.json | 2 +- .../si-terminate-session-request.json | 2 +- .../si-terminate-session-response.json | 2 +- schemas/cache/core/assets/audio-asset.json | 6 + schemas/cache/core/assets/brief-asset.json | 11 + schemas/cache/core/assets/catalog-asset.json | 11 + schemas/cache/core/assets/css-asset.json | 6 + schemas/cache/core/assets/daast-asset.json | 115 +- schemas/cache/core/assets/html-asset.json | 6 + schemas/cache/core/assets/image-asset.json | 6 + .../cache/core/assets/javascript-asset.json | 6 + schemas/cache/core/assets/markdown-asset.json | 6 + schemas/cache/core/assets/text-asset.json | 6 + schemas/cache/core/assets/url-asset.json | 10 +- schemas/cache/core/assets/vast-asset.json | 133 +- schemas/cache/core/assets/video-asset.json | 6 + schemas/cache/core/assets/webhook-asset.json | 10 +- schemas/cache/core/creative-asset.json | 9 +- schemas/cache/core/creative-manifest.json | 9 +- schemas/cache/core/offering-asset-group.json | 14 +- schemas/cache/core/offering.json | 5 + schemas/cache/creative/asset-types/index.json | 11 +- .../creative/list-creatives-response.json | 13 +- .../creative/sync-creatives-request.json | 5 + schemas/cache/extensions/index.json | 2 +- .../governance/check-governance-request.json | 2 +- .../get-plan-audit-logs-request.json | 2 +- .../report-plan-outcome-request.json | 2 +- schemas/cache/index.json | 2 +- .../cache/media-buy/get-products-request.json | 19 +- .../media-buy/get-products-response.json | 120 +- .../si-get-offering-request.json | 7 +- .../si-initiate-session-request.json | 9 +- scripts/post_generate_fixes.py | 157 + src/adcp/types/_generated.py | 63 +- .../types/generated_poc/a2ui/bound_value.py | 2 +- .../types/generated_poc/a2ui/component.py | 2 +- .../types/generated_poc/a2ui/si_catalog.py | 2 +- src/adcp/types/generated_poc/a2ui/surface.py | 2 +- .../types/generated_poc/a2ui/user_action.py | 2 +- .../account/get_account_financials_request.py | 2 +- .../get_account_financials_response.py | 2 +- .../account/list_accounts_request.py | 2 +- .../account/list_accounts_response.py | 2 +- .../account/report_usage_request.py | 2 +- .../account/report_usage_response.py | 2 +- .../account/sync_accounts_request.py | 2 +- .../account/sync_accounts_response.py | 2 +- .../account/sync_governance_request.py | 2 +- .../account/sync_governance_response.py | 2 +- src/adcp/types/generated_poc/adagents.py | 14 +- .../types/generated_poc/brand/__init__.py | 2 +- .../brand/acquire_rights_request.py | 2 +- .../brand/acquire_rights_response.py | 10 +- .../brand/creative_approval_request.py | 2 +- .../brand/creative_approval_response.py | 10 +- .../brand/get_brand_identity_request.py | 2 +- .../brand/get_brand_identity_response.py | 2 +- .../generated_poc/brand/get_rights_request.py | 2 +- .../brand/get_rights_response.py | 2 +- .../brand/revocation_notification.py | 2 +- .../brand/rights_pricing_option.py | 2 +- .../types/generated_poc/brand/rights_terms.py | 2 +- .../brand/update_rights_request.py | 2 +- .../brand/update_rights_response.py | 2 +- .../calibrate_content_request.py | 16 +- .../calibrate_content_response.py | 2 +- .../create_content_standards_request.py | 28 +- .../create_content_standards_response.py | 2 +- .../get_content_standards_request.py | 2 +- .../get_content_standards_response.py | 34 +- .../get_media_buy_artifacts_request.py | 2 +- .../get_media_buy_artifacts_response.py | 16 +- .../list_content_standards_request.py | 2 +- .../list_content_standards_response.py | 34 +- .../update_content_standards_request.py | 28 +- .../update_content_standards_response.py | 2 +- .../validate_content_delivery_request.py | 16 +- .../validate_content_delivery_response.py | 2 +- .../bundled/core/tasks_get_request.py | 2 +- .../bundled/core/tasks_get_response.py | 2 +- .../bundled/core/tasks_list_request.py | 2 +- .../bundled/core/tasks_list_response.py | 2 +- .../creative/get_creative_delivery_request.py | 2 +- .../get_creative_delivery_response.py | 147 +- .../creative/get_creative_features_request.py | 147 +- .../get_creative_features_response.py | 2 +- .../creative/list_creative_formats_request.py | 2 +- .../list_creative_formats_response.py | 22 +- .../creative/list_creatives_request.py | 2 +- .../creative/list_creatives_response.py | 167 +- .../creative/preview_creative_request.py | 286 +- .../creative/preview_creative_response.py | 159 +- .../creative/sync_creatives_request.py | 149 +- .../creative/sync_creatives_response.py | 8 +- .../media_buy/build_creative_request.py | 147 +- .../media_buy/build_creative_response.py | 292 +- .../media_buy/create_media_buy_request.py | 163 +- .../media_buy/create_media_buy_response.py | 38 +- .../get_media_buy_delivery_request.py | 2 +- .../get_media_buy_delivery_response.py | 2 +- .../media_buy/get_media_buys_request.py | 2 +- .../media_buy/get_media_buys_response.py | 2 +- .../bundled/media_buy/get_products_request.py | 54 +- .../media_buy/get_products_response.py | 126 +- .../list_creative_formats_request.py | 2 +- .../list_creative_formats_response.py | 22 +- .../bundled/media_buy/log_event_request.py | 2 +- .../bundled/media_buy/log_event_response.py | 2 +- .../bundled/media_buy/package_request.py | 163 +- .../provide_performance_feedback_request.py | 2 +- .../provide_performance_feedback_response.py | 2 +- .../media_buy/sync_audiences_request.py | 2 +- .../media_buy/sync_audiences_response.py | 2 +- .../media_buy/sync_catalogs_request.py | 2 +- .../media_buy/sync_catalogs_response.py | 2 +- .../media_buy/sync_event_sources_request.py | 2 +- .../media_buy/sync_event_sources_response.py | 2 +- .../media_buy/update_media_buy_request.py | 308 +- .../media_buy/update_media_buy_response.py | 16 +- .../property/create_property_list_request.py | 8 +- .../property/create_property_list_response.py | 18 +- .../property/delete_property_list_request.py | 2 +- .../property/delete_property_list_response.py | 2 +- .../property/get_property_list_request.py | 2 +- .../property/get_property_list_response.py | 18 +- .../property/list_property_lists_request.py | 2 +- .../property/list_property_lists_response.py | 18 +- .../property/update_property_list_request.py | 8 +- .../property/update_property_list_response.py | 18 +- .../validate_property_delivery_request.py | 2 +- .../validate_property_delivery_response.py | 10 +- .../protocol/get_adcp_capabilities_request.py | 2 +- .../get_adcp_capabilities_response.py | 2 +- .../signals/activate_signal_request.py | 6 +- .../signals/activate_signal_response.py | 14 +- .../bundled/signals/get_signals_request.py | 10 +- .../bundled/signals/get_signals_response.py | 28 +- .../si_get_offering_request.py | 13 +- .../si_get_offering_response.py | 2 +- .../si_initiate_session_request.py | 16 +- .../si_initiate_session_response.py | 2 +- .../si_send_message_request.py | 2 +- .../si_send_message_response.py | 2 +- .../si_terminate_session_request.py | 2 +- .../si_terminate_session_response.py | 2 +- .../collection/base_collection_source.py | 8 +- .../collection/collection_list.py | 2 +- .../collection_list_changed_webhook.py | 6 +- .../collection/collection_list_filters.py | 2 +- .../create_collection_list_request.py | 2 +- .../create_collection_list_response.py | 2 +- .../delete_collection_list_request.py | 2 +- .../delete_collection_list_response.py | 2 +- .../collection/get_collection_list_request.py | 2 +- .../get_collection_list_response.py | 2 +- .../list_collection_lists_request.py | 2 +- .../list_collection_lists_response.py | 2 +- .../update_collection_list_request.py | 2 +- .../update_collection_list_response.py | 2 +- .../comply_test_controller_request.py | 2 +- .../comply_test_controller_response.py | 2 +- .../content_standards/artifact.py | 16 +- .../artifact_webhook_payload.py | 2 +- .../calibrate_content_request.py | 2 +- .../calibrate_content_response.py | 2 +- .../content_standards/content_standards.py | 2 +- .../create_content_standards_request.py | 6 +- .../create_content_standards_response.py | 2 +- .../get_content_standards_request.py | 2 +- .../get_media_buy_artifacts_request.py | 2 +- .../get_media_buy_artifacts_response.py | 2 +- .../list_content_standards_request.py | 2 +- .../list_content_standards_response.py | 2 +- .../update_content_standards_request.py | 6 +- .../update_content_standards_response.py | 2 +- .../validate_content_delivery_request.py | 2 +- .../validate_content_delivery_response.py | 2 +- src/adcp/types/generated_poc/core/account.py | 2 +- .../types/generated_poc/core/account_ref.py | 2 +- .../generated_poc/core/activation_key.py | 10 +- .../generated_poc/core/ad_inventory_config.py | 2 +- .../core/agent_encryption_key.py | 10 +- .../generated_poc/core/agent_signing_key.py | 2 +- src/adcp/types/generated_poc/core/app_item.py | 2 +- .../generated_poc/core/assets/audio_asset.py | 10 +- .../generated_poc/core/assets/brief_asset.py | 13 +- .../core/assets/catalog_asset.py | 13 +- .../generated_poc/core/assets/css_asset.py | 10 +- .../generated_poc/core/assets/daast_asset.py | 35 +- .../generated_poc/core/assets/html_asset.py | 10 +- .../generated_poc/core/assets/image_asset.py | 10 +- .../core/assets/javascript_asset.py | 10 +- .../core/assets/markdown_asset.py | 10 +- .../generated_poc/core/assets/text_asset.py | 10 +- .../generated_poc/core/assets/url_asset.py | 19 +- .../generated_poc/core/assets/vast_asset.py | 35 +- .../generated_poc/core/assets/video_asset.py | 10 +- .../core/assets/webhook_asset.py | 10 +- .../generated_poc/core/async_response_data.py | 2 +- .../generated_poc/core/attribution_window.py | 2 +- .../generated_poc/core/audience_member.py | 2 +- .../generated_poc/core/audience_selector.py | 18 +- src/adcp/types/generated_poc/core/brand_id.py | 2 +- .../types/generated_poc/core/brand_ref.py | 2 +- .../generated_poc/core/business_entity.py | 2 +- .../generated_poc/core/cancellation_policy.py | 2 +- src/adcp/types/generated_poc/core/catalog.py | 2 +- .../core/catalog_field_mapping.py | 2 +- .../types/generated_poc/core/catchment.py | 2 +- .../types/generated_poc/core/collection.py | 2 +- .../core/collection_distribution.py | 2 +- .../generated_poc/core/collection_list_ref.py | 2 +- .../generated_poc/core/collection_selector.py | 2 +- .../generated_poc/core/content_rating.py | 2 +- src/adcp/types/generated_poc/core/context.py | 2 +- .../generated_poc/core/creative_asset.py | 6 +- .../generated_poc/core/creative_assignment.py | 2 +- .../generated_poc/core/creative_brief.py | 2 +- .../core/creative_consumption.py | 2 +- .../generated_poc/core/creative_filters.py | 2 +- .../types/generated_poc/core/creative_item.py | 6 +- .../generated_poc/core/creative_manifest.py | 4 +- .../generated_poc/core/creative_policy.py | 2 +- .../generated_poc/core/creative_variable.py | 2 +- .../generated_poc/core/creative_variant.py | 2 +- .../core/data_provider_signal_selector.py | 8 +- .../types/generated_poc/core/date_range.py | 2 +- .../generated_poc/core/datetime_range.py | 2 +- .../generated_poc/core/daypart_target.py | 2 +- .../generated_poc/core/deadline_policy.py | 2 +- .../generated_poc/core/delivery_forecast.py | 2 +- .../generated_poc/core/delivery_metrics.py | 2 +- .../types/generated_poc/core/deployment.py | 6 +- .../types/generated_poc/core/destination.py | 6 +- .../generated_poc/core/destination_item.py | 2 +- .../generated_poc/core/diagnostic_issue.py | 2 +- src/adcp/types/generated_poc/core/duration.py | 2 +- .../generated_poc/core/education_item.py | 2 +- src/adcp/types/generated_poc/core/error.py | 2 +- src/adcp/types/generated_poc/core/event.py | 2 +- .../generated_poc/core/event_custom_data.py | 2 +- .../generated_poc/core/event_source_health.py | 2 +- src/adcp/types/generated_poc/core/ext.py | 2 +- .../generated_poc/core/feature_requirement.py | 2 +- .../types/generated_poc/core/flight_item.py | 2 +- .../generated_poc/core/forecast_point.py | 2 +- .../generated_poc/core/forecast_range.py | 2 +- src/adcp/types/generated_poc/core/format.py | 6 +- .../types/generated_poc/core/format_id.py | 2 +- .../types/generated_poc/core/frequency_cap.py | 2 +- .../core/generation_credential.py | 2 +- .../core/geo_breakdown_support.py | 2 +- .../types/generated_poc/core/hotel_item.py | 2 +- .../types/generated_poc/core/identifier.py | 2 +- .../generated_poc/core/industry_identifier.py | 2 +- .../generated_poc/core/insertion_order.py | 2 +- .../types/generated_poc/core/installment.py | 2 +- .../core/installment_deadlines.py | 2 +- src/adcp/types/generated_poc/core/job_item.py | 2 +- .../generated_poc/core/limited_series.py | 2 +- .../generated_poc/core/material_deadline.py | 2 +- .../generated_poc/core/mcp_webhook_payload.py | 2 +- .../core/measurement_readiness.py | 2 +- .../generated_poc/core/measurement_terms.py | 2 +- .../generated_poc/core/measurement_window.py | 2 +- .../types/generated_poc/core/media_buy.py | 2 +- .../generated_poc/core/media_buy_features.py | 2 +- src/adcp/types/generated_poc/core/offering.py | 2 +- .../core/offering_asset_group.py | 62 +- .../generated_poc/core/optimization_goal.py | 16 +- .../generated_poc/core/outcome_measurement.py | 2 +- src/adcp/types/generated_poc/core/overlay.py | 2 +- src/adcp/types/generated_poc/core/package.py | 2 +- .../generated_poc/core/pagination_request.py | 2 +- .../generated_poc/core/pagination_response.py | 2 +- .../core/performance_feedback.py | 2 +- .../core/performance_standard.py | 2 +- .../types/generated_poc/core/placement.py | 2 +- .../core/placement_definition.py | 2 +- .../generated_poc/core/planned_delivery.py | 2 +- src/adcp/types/generated_poc/core/price.py | 2 +- .../generated_poc/core/pricing_option.py | 2 +- src/adcp/types/generated_poc/core/product.py | 2 +- .../generated_poc/core/product_allocation.py | 2 +- .../generated_poc/core/product_filters.py | 2 +- src/adcp/types/generated_poc/core/property.py | 2 +- .../types/generated_poc/core/property_id.py | 2 +- .../generated_poc/core/property_list_ref.py | 2 +- .../types/generated_poc/core/property_tag.py | 2 +- src/adcp/types/generated_poc/core/proposal.py | 2 +- .../generated_poc/core/protocol_envelope.py | 2 +- .../types/generated_poc/core/provenance.py | 2 +- .../core/publisher_property_selector.py | 8 +- .../core/push_notification_config.py | 2 +- .../generated_poc/core/real_estate_item.py | 2 +- .../generated_poc/core/reference_asset.py | 2 +- .../core/reporting_capabilities.py | 2 +- .../generated_poc/core/reporting_webhook.py | 2 +- .../core/requirements/asset_requirements.py | 2 +- .../requirements/audio_asset_requirements.py | 2 +- .../requirements/catalog_field_binding.py | 8 +- .../core/requirements/catalog_requirements.py | 2 +- .../requirements/css_asset_requirements.py | 2 +- .../requirements/daast_asset_requirements.py | 2 +- .../requirements/html_asset_requirements.py | 2 +- .../requirements/image_asset_requirements.py | 2 +- .../javascript_asset_requirements.py | 2 +- .../markdown_asset_requirements.py | 2 +- .../requirements/offering_asset_constraint.py | 2 +- .../requirements/text_asset_requirements.py | 2 +- .../requirements/url_asset_requirements.py | 2 +- .../requirements/vast_asset_requirements.py | 2 +- .../requirements/video_asset_requirements.py | 2 +- .../webhook_asset_requirements.py | 2 +- src/adcp/types/generated_poc/core/response.py | 2 +- .../generated_poc/core/rights_constraint.py | 2 +- .../generated_poc/core/signal_definition.py | 2 +- .../generated_poc/core/signal_filters.py | 2 +- .../types/generated_poc/core/signal_id.py | 6 +- .../generated_poc/core/signal_pricing.py | 12 +- .../core/signal_pricing_option.py | 2 +- .../generated_poc/core/signal_targeting.py | 10 +- src/adcp/types/generated_poc/core/special.py | 2 +- .../types/generated_poc/core/start_timing.py | 2 +- .../types/generated_poc/core/store_item.py | 2 +- src/adcp/types/generated_poc/core/talent.py | 2 +- .../types/generated_poc/core/targeting.py | 2 +- .../generated_poc/core/tasks_get_request.py | 2 +- .../generated_poc/core/tasks_get_response.py | 2 +- .../generated_poc/core/tasks_list_request.py | 2 +- .../generated_poc/core/tasks_list_response.py | 2 +- .../types/generated_poc/core/user_match.py | 2 +- .../types/generated_poc/core/vehicle_item.py | 2 +- .../core/vendor_pricing_option.py | 12 +- .../generated_poc/core/x_entity_types.py | 2 +- .../creative/creative_feature_result.py | 2 +- .../creative/get_creative_delivery_request.py | 2 +- .../get_creative_delivery_response.py | 2 +- .../creative/get_creative_features_request.py | 2 +- .../get_creative_features_response.py | 2 +- .../creative/list_creative_formats_request.py | 2 +- .../list_creative_formats_response.py | 2 +- .../creative/list_creatives_request.py | 2 +- .../creative/list_creatives_response.py | 6 +- .../creative/preview_creative_request.py | 2 +- .../creative/preview_creative_response.py | 8 +- .../generated_poc/creative/preview_render.py | 8 +- ...creatives_async_response_input_required.py | 2 +- ...sync_creatives_async_response_submitted.py | 2 +- .../sync_creatives_async_response_working.py | 2 +- .../creative/sync_creatives_request.py | 2 +- .../creative/sync_creatives_response.py | 4 +- .../generated_poc/enums/account_status.py | 2 +- .../generated_poc/enums/action_source.py | 2 +- .../generated_poc/enums/adcp_protocol.py | 2 +- .../generated_poc/enums/adjustment_kind.py | 2 +- .../enums/advertiser_industry.py | 2 +- .../enums/age_verification_method.py | 2 +- .../generated_poc/enums/assessment_status.py | 2 +- .../generated_poc/enums/asset_content_type.py | 2 +- .../generated_poc/enums/attribution_model.py | 2 +- .../generated_poc/enums/audience_source.py | 2 +- .../types/generated_poc/enums/auth_scheme.py | 2 +- .../generated_poc/enums/available_metric.py | 2 +- .../generated_poc/enums/brand_agent_type.py | 2 +- .../types/generated_poc/enums/canceled_by.py | 2 +- .../generated_poc/enums/catalog_action.py | 2 +- .../enums/catalog_item_status.py | 2 +- .../types/generated_poc/enums/catalog_type.py | 2 +- .../types/generated_poc/enums/channels.py | 2 +- .../enums/cloud_storage_protocol.py | 2 +- .../enums/co_branding_requirement.py | 2 +- .../generated_poc/enums/collection_cadence.py | 2 +- .../enums/collection_relationship.py | 2 +- .../generated_poc/enums/collection_status.py | 2 +- .../generated_poc/enums/consent_basis.py | 2 +- .../generated_poc/enums/content_id_type.py | 2 +- .../enums/content_rating_system.py | 2 +- .../generated_poc/enums/creative_action.py | 2 +- .../enums/creative_agent_capability.py | 2 +- .../enums/creative_approval_status.py | 2 +- .../enums/creative_identifier_type.py | 2 +- .../generated_poc/enums/creative_quality.py | 2 +- .../enums/creative_sort_field.py | 2 +- .../generated_poc/enums/creative_status.py | 2 +- .../enums/daast_tracking_event.py | 2 +- .../generated_poc/enums/daast_version.py | 2 +- .../types/generated_poc/enums/day_of_week.py | 2 +- .../enums/delegation_authority.py | 2 +- .../generated_poc/enums/delivery_type.py | 2 +- .../generated_poc/enums/demographic_system.py | 2 +- .../generated_poc/enums/derivative_type.py | 2 +- .../generated_poc/enums/device_platform.py | 2 +- .../types/generated_poc/enums/device_type.py | 2 +- .../enums/digital_source_type.py | 2 +- .../generated_poc/enums/dimension_unit.py | 2 +- .../enums/disclosure_persistence.py | 2 +- .../enums/disclosure_position.py | 2 +- .../generated_poc/enums/distance_unit.py | 2 +- .../enums/distribution_identifier_type.py | 2 +- .../types/generated_poc/enums/error_code.py | 2 +- .../enums/escalation_severity.py | 2 +- .../types/generated_poc/enums/event_type.py | 2 +- .../types/generated_poc/enums/exclusivity.py | 2 +- .../types/generated_poc/enums/feed_format.py | 2 +- .../generated_poc/enums/feedback_source.py | 2 +- .../generated_poc/enums/forecast_method.py | 2 +- .../enums/forecast_range_unit.py | 2 +- .../enums/forecastable_metric.py | 2 +- .../enums/format_id_parameter.py | 2 +- .../enums/frequency_cap_scope.py | 4 +- .../generated_poc/enums/genre_taxonomy.py | 2 +- .../types/generated_poc/enums/geo_level.py | 2 +- .../generated_poc/enums/governance_domain.py | 2 +- .../generated_poc/enums/governance_mode.py | 2 +- .../generated_poc/enums/governance_phase.py | 2 +- .../generated_poc/enums/history_entry_type.py | 2 +- .../types/generated_poc/enums/http_method.py | 2 +- .../generated_poc/enums/identifier_types.py | 2 +- .../generated_poc/enums/installment_status.py | 2 +- .../enums/javascript_module_type.py | 2 +- .../enums/landing_page_requirement.py | 2 +- .../generated_poc/enums/makegood_remedy.py | 2 +- .../generated_poc/enums/markdown_flavor.py | 2 +- .../generated_poc/enums/match_id_type.py | 2 +- .../generated_poc/enums/media_buy_status.py | 2 +- .../types/generated_poc/enums/metric_type.py | 2 +- .../types/generated_poc/enums/metro_system.py | 2 +- .../generated_poc/enums/notification_type.py | 2 +- .../types/generated_poc/enums/outcome_type.py | 2 +- src/adcp/types/generated_poc/enums/pacing.py | 2 +- .../enums/performance_standard_metric.py | 2 +- .../generated_poc/enums/policy_category.py | 2 +- .../generated_poc/enums/policy_enforcement.py | 2 +- .../generated_poc/enums/postal_system.py | 2 +- .../enums/preview_output_format.py | 2 +- .../generated_poc/enums/pricing_model.py | 2 +- .../generated_poc/enums/production_quality.py | 2 +- .../generated_poc/enums/property_type.py | 2 +- .../generated_poc/enums/proposal_status.py | 2 +- .../enums/publisher_identifier_types.py | 2 +- .../generated_poc/enums/purchase_type.py | 2 +- .../types/generated_poc/enums/reach_unit.py | 2 +- .../enums/reporting_frequency.py | 2 +- .../generated_poc/enums/response_type.py | 2 +- .../enums/restricted_attribute.py | 2 +- .../types/generated_poc/enums/right_type.py | 2 +- .../types/generated_poc/enums/right_use.py | 2 +- .../generated_poc/enums/si_session_status.py | 2 +- .../enums/signal_catalog_type.py | 2 +- .../generated_poc/enums/signal_source.py | 2 +- .../generated_poc/enums/signal_value_type.py | 2 +- .../generated_poc/enums/sort_direction.py | 2 +- .../types/generated_poc/enums/sort_metric.py | 2 +- .../generated_poc/enums/special_category.py | 2 +- .../types/generated_poc/enums/specialism.py | 2 +- .../types/generated_poc/enums/talent_role.py | 2 +- .../types/generated_poc/enums/task_status.py | 2 +- .../types/generated_poc/enums/task_type.py | 2 +- .../generated_poc/enums/transport_mode.py | 2 +- .../types/generated_poc/enums/uid_type.py | 2 +- .../generated_poc/enums/universal_macro.py | 2 +- .../generated_poc/enums/update_frequency.py | 2 +- .../generated_poc/enums/url_asset_type.py | 2 +- .../generated_poc/enums/validation_mode.py | 2 +- .../enums/vast_tracking_event.py | 2 +- .../types/generated_poc/enums/vast_version.py | 2 +- .../enums/viewability_standard.py | 2 +- .../types/generated_poc/enums/wcag_level.py | 2 +- .../enums/webhook_response_type.py | 2 +- .../enums/webhook_security_method.py | 2 +- .../error_details/account_setup_required.py | 2 +- .../error_details/audience_too_small.py | 2 +- .../error_details/budget_too_low.py | 2 +- .../generated_poc/error_details/conflict.py | 2 +- .../error_details/creative_rejected.py | 2 +- .../error_details/policy_violation.py | 2 +- .../error_details/rate_limited.py | 2 +- .../error_details/vendor_error_codes.py | 2 +- .../extensions/extension_meta.py | 6 +- .../governance/attribute_definition.py | 2 +- .../governance/audience_constraints.py | 2 +- .../governance/check_governance_request.py | 9 +- .../governance/check_governance_response.py | 2 +- .../governance/get_plan_audit_logs_request.py | 4 +- .../get_plan_audit_logs_response.py | 2 +- .../governance/policy_category_definition.py | 2 +- .../generated_poc/governance/policy_entry.py | 2 +- .../generated_poc/governance/policy_ref.py | 2 +- .../governance/report_plan_outcome_request.py | 9 +- .../report_plan_outcome_response.py | 2 +- .../governance/sync_plans_request.py | 2 +- .../governance/sync_plans_response.py | 6 +- ..._creative_async_response_input_required.py | 2 +- ...build_creative_async_response_submitted.py | 2 +- .../build_creative_async_response_working.py | 2 +- .../media_buy/build_creative_request.py | 2 +- .../media_buy/build_creative_response.py | 2 +- ...media_buy_async_response_input_required.py | 2 +- ...eate_media_buy_async_response_submitted.py | 2 +- ...create_media_buy_async_response_working.py | 2 +- .../media_buy/create_media_buy_request.py | 2 +- .../media_buy/create_media_buy_response.py | 4 +- .../get_media_buy_delivery_request.py | 2 +- .../get_media_buy_delivery_response.py | 2 +- .../media_buy/get_media_buys_request.py | 2 +- .../media_buy/get_media_buys_response.py | 2 +- ..._products_async_response_input_required.py | 2 +- .../get_products_async_response_submitted.py | 2 +- .../get_products_async_response_working.py | 2 +- .../media_buy/get_products_request.py | 48 +- .../media_buy/get_products_response.py | 92 +- .../list_creative_formats_request.py | 2 +- .../list_creative_formats_response.py | 2 +- .../media_buy/log_event_request.py | 2 +- .../media_buy/log_event_response.py | 2 +- .../media_buy/package_request.py | 2 +- .../generated_poc/media_buy/package_update.py | 2 +- .../provide_performance_feedback_request.py | 2 +- .../provide_performance_feedback_response.py | 2 +- .../media_buy/sync_audiences_request.py | 2 +- .../media_buy/sync_audiences_response.py | 2 +- ..._catalogs_async_response_input_required.py | 2 +- .../sync_catalogs_async_response_submitted.py | 2 +- .../sync_catalogs_async_response_working.py | 2 +- .../media_buy/sync_catalogs_request.py | 2 +- .../media_buy/sync_catalogs_response.py | 2 +- .../media_buy/sync_event_sources_request.py | 2 +- .../media_buy/sync_event_sources_response.py | 2 +- ...media_buy_async_response_input_required.py | 2 +- ...date_media_buy_async_response_submitted.py | 2 +- ...update_media_buy_async_response_working.py | 2 +- .../media_buy/update_media_buy_request.py | 2 +- .../media_buy/update_media_buy_response.py | 2 +- .../pricing_options/cpa_option.py | 4 +- .../pricing_options/cpc_option.py | 4 +- .../pricing_options/cpcv_option.py | 4 +- .../pricing_options/cpm_option.py | 6 +- .../pricing_options/cpp_option.py | 6 +- .../pricing_options/cpv_option.py | 6 +- .../pricing_options/flat_rate_option.py | 6 +- .../pricing_options/price_breakdown.py | 2 +- .../pricing_options/price_guidance.py | 2 +- .../pricing_options/time_option.py | 4 +- .../pricing_options/vcpm_option.py | 4 +- .../property/authorization_result.py | 2 +- .../property/base_property_source.py | 8 +- .../property/create_property_list_request.py | 2 +- .../property/create_property_list_response.py | 2 +- .../property/delete_property_list_request.py | 2 +- .../property/delete_property_list_response.py | 2 +- .../generated_poc/property/delivery_record.py | 2 +- .../property/get_property_list_request.py | 2 +- .../property/get_property_list_response.py | 3 +- .../property/list_property_lists_request.py | 2 +- .../property/list_property_lists_response.py | 2 +- .../generated_poc/property/property_error.py | 2 +- .../property/property_feature.py | 2 +- .../property/property_feature_definition.py | 2 +- .../property/property_feature_result.py | 2 +- .../property/property_feature_value.py | 2 +- .../generated_poc/property/property_list.py | 2 +- .../property/property_list_changed_webhook.py | 6 +- .../property/property_list_filters.py | 2 +- .../property/update_property_list_request.py | 2 +- .../property/update_property_list_response.py | 2 +- .../validate_property_delivery_request.py | 2 +- .../validate_property_delivery_response.py | 2 +- .../property/validation_result.py | 6 +- .../protocol/get_adcp_capabilities_request.py | 2 +- .../get_adcp_capabilities_response.py | 2 +- .../signals/activate_signal_request.py | 2 +- .../signals/activate_signal_response.py | 2 +- .../signals/get_signals_request.py | 2 +- .../signals/get_signals_response.py | 2 +- .../sponsored_intelligence/si_capabilities.py | 2 +- .../si_get_offering_request.py | 8 +- .../si_get_offering_response.py | 2 +- .../sponsored_intelligence/si_identity.py | 2 +- .../si_initiate_session_request.py | 11 +- .../si_initiate_session_response.py | 2 +- .../si_send_message_request.py | 2 +- .../si_send_message_response.py | 2 +- .../si_terminate_session_request.py | 2 +- .../si_terminate_session_response.py | 2 +- .../sponsored_intelligence/si_ui_element.py | 2 +- .../generated_poc/tmp/available_package.py | 2 +- .../tmp/context_match_request.py | 4 +- .../tmp/context_match_response.py | 4 +- src/adcp/types/generated_poc/tmp/error.py | 4 +- .../tmp/identity_match_request.py | 4 +- .../tmp/identity_match_response.py | 4 +- src/adcp/types/generated_poc/tmp/offer.py | 2 +- .../types/generated_poc/tmp/offer_price.py | 2 +- .../tmp/provider_registration.py | 2 +- tests/test_literal_discriminator_defaults.py | 171 + 675 files changed, 15602 insertions(+), 21614 deletions(-) create mode 100644 tests/test_literal_discriminator_defaults.py diff --git a/schemas/cache/bundled/content-standards/calibrate-content-request.json b/schemas/cache/bundled/content-standards/calibrate-content-request.json index beae4e6f0..4bd0342d6 100644 --- a/schemas/cache/bundled/content-standards/calibrate-content-request.json +++ b/schemas/cache/bundled/content-standards/calibrate-content-request.json @@ -1888,7 +1888,7 @@ } }, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.329Z", + "generatedAt": "2026-04-22T04:00:56.627Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/content-standards/calibrate-content-response.json b/schemas/cache/bundled/content-standards/calibrate-content-response.json index 3f6de0038..42e8e5e3b 100644 --- a/schemas/cache/bundled/content-standards/calibrate-content-response.json +++ b/schemas/cache/bundled/content-standards/calibrate-content-response.json @@ -161,7 +161,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.331Z", + "generatedAt": "2026-04-22T04:00:56.629Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/content-standards/create-content-standards-request.json b/schemas/cache/bundled/content-standards/create-content-standards-request.json index 01febd181..71f11c6c8 100644 --- a/schemas/cache/bundled/content-standards/create-content-standards-request.json +++ b/schemas/cache/bundled/content-standards/create-content-standards-request.json @@ -4081,7 +4081,7 @@ } }, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.338Z", + "generatedAt": "2026-04-22T04:00:56.635Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/content-standards/create-content-standards-response.json b/schemas/cache/bundled/content-standards/create-content-standards-response.json index a76830124..c9032fd0d 100644 --- a/schemas/cache/bundled/content-standards/create-content-standards-response.json +++ b/schemas/cache/bundled/content-standards/create-content-standards-response.json @@ -109,7 +109,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.341Z", + "generatedAt": "2026-04-22T04:00:56.638Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/content-standards/get-content-standards-request.json b/schemas/cache/bundled/content-standards/get-content-standards-request.json index f70575c86..968ed112c 100644 --- a/schemas/cache/bundled/content-standards/get-content-standards-request.json +++ b/schemas/cache/bundled/content-standards/get-content-standards-request.json @@ -31,7 +31,7 @@ "standards_id" ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.342Z", + "generatedAt": "2026-04-22T04:00:56.638Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/content-standards/get-content-standards-response.json b/schemas/cache/bundled/content-standards/get-content-standards-response.json index 379052953..23fcca6f1 100644 --- a/schemas/cache/bundled/content-standards/get-content-standards-response.json +++ b/schemas/cache/bundled/content-standards/get-content-standards-response.json @@ -4310,7 +4310,7 @@ } }, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.348Z", + "generatedAt": "2026-04-22T04:00:56.644Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/content-standards/get-media-buy-artifacts-request.json b/schemas/cache/bundled/content-standards/get-media-buy-artifacts-request.json index 4bb7d483b..088468a17 100644 --- a/schemas/cache/bundled/content-standards/get-media-buy-artifacts-request.json +++ b/schemas/cache/bundled/content-standards/get-media-buy-artifacts-request.json @@ -227,7 +227,7 @@ "media_buy_id" ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.351Z", + "generatedAt": "2026-04-22T04:00:56.648Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/content-standards/get-media-buy-artifacts-response.json b/schemas/cache/bundled/content-standards/get-media-buy-artifacts-response.json index 7a2732829..2abd24031 100644 --- a/schemas/cache/bundled/content-standards/get-media-buy-artifacts-response.json +++ b/schemas/cache/bundled/content-standards/get-media-buy-artifacts-response.json @@ -2056,7 +2056,7 @@ } }, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.354Z", + "generatedAt": "2026-04-22T04:00:56.651Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/content-standards/list-content-standards-request.json b/schemas/cache/bundled/content-standards/list-content-standards-request.json index f104706a6..dff6ab823 100644 --- a/schemas/cache/bundled/content-standards/list-content-standards-request.json +++ b/schemas/cache/bundled/content-standards/list-content-standards-request.json @@ -114,7 +114,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.356Z", + "generatedAt": "2026-04-22T04:00:56.653Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/content-standards/list-content-standards-response.json b/schemas/cache/bundled/content-standards/list-content-standards-response.json index a20facda7..30bfe965e 100644 --- a/schemas/cache/bundled/content-standards/list-content-standards-response.json +++ b/schemas/cache/bundled/content-standards/list-content-standards-response.json @@ -4339,7 +4339,7 @@ } }, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.362Z", + "generatedAt": "2026-04-22T04:00:56.658Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/content-standards/update-content-standards-request.json b/schemas/cache/bundled/content-standards/update-content-standards-request.json index 0fe32a194..0cd222ae8 100644 --- a/schemas/cache/bundled/content-standards/update-content-standards-request.json +++ b/schemas/cache/bundled/content-standards/update-content-standards-request.json @@ -4070,7 +4070,7 @@ } }, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.369Z", + "generatedAt": "2026-04-22T04:00:56.667Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/content-standards/update-content-standards-response.json b/schemas/cache/bundled/content-standards/update-content-standards-response.json index 7e962091b..1b4ddb78f 100644 --- a/schemas/cache/bundled/content-standards/update-content-standards-response.json +++ b/schemas/cache/bundled/content-standards/update-content-standards-response.json @@ -124,7 +124,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.372Z", + "generatedAt": "2026-04-22T04:00:56.671Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/content-standards/validate-content-delivery-request.json b/schemas/cache/bundled/content-standards/validate-content-delivery-request.json index d6f5e92e1..7da59b230 100644 --- a/schemas/cache/bundled/content-standards/validate-content-delivery-request.json +++ b/schemas/cache/bundled/content-standards/validate-content-delivery-request.json @@ -1942,7 +1942,7 @@ } }, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.375Z", + "generatedAt": "2026-04-22T04:00:56.673Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/content-standards/validate-content-delivery-response.json b/schemas/cache/bundled/content-standards/validate-content-delivery-response.json index 7999d9400..0abd23abb 100644 --- a/schemas/cache/bundled/content-standards/validate-content-delivery-response.json +++ b/schemas/cache/bundled/content-standards/validate-content-delivery-response.json @@ -188,7 +188,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.377Z", + "generatedAt": "2026-04-22T04:00:56.674Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/core/tasks-get-request.json b/schemas/cache/bundled/core/tasks-get-request.json index 099e90f26..0d3eff60d 100644 --- a/schemas/cache/bundled/core/tasks-get-request.json +++ b/schemas/cache/bundled/core/tasks-get-request.json @@ -53,7 +53,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.378Z", + "generatedAt": "2026-04-22T04:00:56.675Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/core/tasks-get-response.json b/schemas/cache/bundled/core/tasks-get-response.json index 2e0c36b69..69b12f1a3 100644 --- a/schemas/cache/bundled/core/tasks-get-response.json +++ b/schemas/cache/bundled/core/tasks-get-response.json @@ -270,7 +270,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.378Z", + "generatedAt": "2026-04-22T04:00:56.676Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/core/tasks-list-request.json b/schemas/cache/bundled/core/tasks-list-request.json index 0b4988edb..1e6b1998a 100644 --- a/schemas/cache/bundled/core/tasks-list-request.json +++ b/schemas/cache/bundled/core/tasks-list-request.json @@ -394,7 +394,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.379Z", + "generatedAt": "2026-04-22T04:00:56.677Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/core/tasks-list-response.json b/schemas/cache/bundled/core/tasks-list-response.json index 203649230..246e7f040 100644 --- a/schemas/cache/bundled/core/tasks-list-response.json +++ b/schemas/cache/bundled/core/tasks-list-response.json @@ -251,7 +251,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.380Z", + "generatedAt": "2026-04-22T04:00:56.678Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/creative/get-creative-delivery-request.json b/schemas/cache/bundled/creative/get-creative-delivery-request.json index cf2aae273..16288128b 100644 --- a/schemas/cache/bundled/creative/get-creative-delivery-request.json +++ b/schemas/cache/bundled/creative/get-creative-delivery-request.json @@ -238,7 +238,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.380Z", + "generatedAt": "2026-04-22T04:00:56.678Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/creative/get-creative-delivery-response.json b/schemas/cache/bundled/creative/get-creative-delivery-response.json index 439b1b67f..9a8129af6 100644 --- a/schemas/cache/bundled/creative/get-creative-delivery-response.json +++ b/schemas/cache/bundled/creative/get-creative-delivery-response.json @@ -1050,15 +1050,20 @@ }, "assets": { "type": "object", - "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance \u2014 each asset must match at least one valid asset type schema.", + "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -1369,6 +1374,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -1380,6 +1386,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -1846,6 +1857,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -1857,6 +1869,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -2208,6 +2225,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -2215,773 +2233,429 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "url" - ], - "additionalProperties": true - }, - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "inline", - "description": "Discriminator indicating VAST is delivered as inline XML content" - }, - "content": { - "type": "string", - "description": "Inline VAST XML content" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", - "type": "string", - "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true }, - "render_guidance": { + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, "additionalProperties": true } }, - "required": [ - "country", - "regulation" - ], "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, + "required": [ + "delivery_type", + "url" + ] + }, + { + "properties": { + "delivery_type": { + "type": "string", + "const": "inline", + "description": "Discriminator indicating VAST is delivered as inline XML content" + }, + "content": { + "type": "string", + "description": "Inline VAST XML content" + } + }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Text Asset", "description": "Text content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Text content" @@ -3276,6 +2950,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -3285,10 +2960,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -3590,6 +3270,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -3599,6 +3280,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -3916,6 +3602,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -3925,6 +3612,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -4248,6 +3940,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -4257,6 +3950,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -4282,7 +3980,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -4441,7 +4139,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -4921,6 +4619,7 @@ } }, "required": [ + "asset_type", "url", "response_type", "security" @@ -4932,6 +4631,11 @@ "description": "CSS stylesheet asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "CSS content" @@ -5226,6 +4930,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5233,371 +4938,379 @@ { "title": "DAAST Asset", "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + }, + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", + "type": "string", + "enum": [ + "1.0", + "1.1" + ] + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating DAAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" + "required": [ + "name" + ], + "additionalProperties": true }, - "transcript_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating DAAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns DAAST XML" } }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -5607,363 +5320,29 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -5989,6 +5368,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5996,6 +5376,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -6189,6 +5580,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -6662,7 +6064,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -7384,7 +6789,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.394Z", + "generatedAt": "2026-04-22T04:00:56.690Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/creative/get-creative-features-request.json b/schemas/cache/bundled/creative/get-creative-features-request.json index 83548fbc0..c884b3251 100644 --- a/schemas/cache/bundled/creative/get-creative-features-request.json +++ b/schemas/cache/bundled/creative/get-creative-features-request.json @@ -63,15 +63,20 @@ }, "assets": { "type": "object", - "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance \u2014 each asset must match at least one valid asset type schema.", + "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -382,6 +387,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -393,6 +399,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -859,6 +870,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -870,6 +882,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -1221,6 +1238,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -1228,773 +1246,429 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "url" - ], - "additionalProperties": true - }, - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "inline", - "description": "Discriminator indicating VAST is delivered as inline XML content" - }, - "content": { - "type": "string", - "description": "Inline VAST XML content" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", - "type": "string", - "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true }, - "render_guidance": { + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, "additionalProperties": true } }, - "required": [ - "country", - "regulation" - ], "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, + "required": [ + "delivery_type", + "url" + ] + }, + { + "properties": { + "delivery_type": { + "type": "string", + "const": "inline", + "description": "Discriminator indicating VAST is delivered as inline XML content" + }, + "content": { + "type": "string", + "description": "Inline VAST XML content" + } + }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Text Asset", "description": "Text content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Text content" @@ -2289,6 +1963,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -2298,10 +1973,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -2603,6 +2283,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -2612,6 +2293,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -2929,6 +2615,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -2938,6 +2625,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -3261,6 +2953,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -3270,6 +2963,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -3295,7 +2993,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -3454,7 +3152,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -3934,6 +3632,7 @@ } }, "required": [ + "asset_type", "url", "response_type", "security" @@ -3945,6 +3644,11 @@ "description": "CSS stylesheet asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "CSS content" @@ -4239,6 +3943,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -4246,371 +3951,379 @@ { "title": "DAAST Asset", "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + }, + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", + "type": "string", + "enum": [ + "1.0", + "1.1" + ] + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating DAAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" + "required": [ + "name" + ], + "additionalProperties": true }, - "transcript_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating DAAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns DAAST XML" + } + }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -4620,363 +4333,29 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -5002,6 +4381,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5009,6 +4389,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -5202,6 +4593,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -5675,7 +5077,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -6344,7 +5749,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.412Z", + "generatedAt": "2026-04-22T04:00:56.703Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/creative/get-creative-features-response.json b/schemas/cache/bundled/creative/get-creative-features-response.json index 75b976e02..250bed465 100644 --- a/schemas/cache/bundled/creative/get-creative-features-response.json +++ b/schemas/cache/bundled/creative/get-creative-features-response.json @@ -223,7 +223,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.417Z", + "generatedAt": "2026-04-22T04:00:56.707Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/creative/list-creative-formats-request.json b/schemas/cache/bundled/creative/list-creative-formats-request.json index 8cfa05e11..6730e008f 100644 --- a/schemas/cache/bundled/creative/list-creative-formats-request.json +++ b/schemas/cache/bundled/creative/list-creative-formats-request.json @@ -478,7 +478,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.418Z", + "generatedAt": "2026-04-22T04:00:56.708Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/creative/list-creative-formats-response.json b/schemas/cache/bundled/creative/list-creative-formats-response.json index 119bb3d2e..dfc3182aa 100644 --- a/schemas/cache/bundled/creative/list-creative-formats-response.json +++ b/schemas/cache/bundled/creative/list-creative-formats-response.json @@ -4093,7 +4093,7 @@ } }, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.423Z", + "generatedAt": "2026-04-22T04:00:56.713Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/creative/list-creatives-request.json b/schemas/cache/bundled/creative/list-creatives-request.json index 9d613d705..1320fc695 100644 --- a/schemas/cache/bundled/creative/list-creatives-request.json +++ b/schemas/cache/bundled/creative/list-creatives-request.json @@ -680,7 +680,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.426Z", + "generatedAt": "2026-04-22T04:00:56.716Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/creative/list-creatives-response.json b/schemas/cache/bundled/creative/list-creatives-response.json index 92ed0231f..52d651c90 100644 --- a/schemas/cache/bundled/creative/list-creatives-response.json +++ b/schemas/cache/bundled/creative/list-creatives-response.json @@ -838,15 +838,20 @@ }, "assets": { "type": "object", - "description": "Assets for this creative, keyed by asset_id", + "description": "Assets for this creative, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -1157,6 +1162,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -1168,6 +1174,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -1634,6 +1645,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -1645,6 +1657,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -1996,6 +2013,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -2003,773 +2021,429 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "url" - ], - "additionalProperties": true - }, - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "inline", - "description": "Discriminator indicating VAST is delivered as inline XML content" - }, - "content": { - "type": "string", - "description": "Inline VAST XML content" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", - "type": "string", - "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true }, - "render_guidance": { + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, "additionalProperties": true } }, - "required": [ - "country", - "regulation" - ], "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, + "required": [ + "delivery_type", + "url" + ] + }, + { + "properties": { + "delivery_type": { + "type": "string", + "const": "inline", + "description": "Discriminator indicating VAST is delivered as inline XML content" + }, + "content": { + "type": "string", + "description": "Inline VAST XML content" + } + }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Text Asset", "description": "Text content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Text content" @@ -3064,6 +2738,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -3073,10 +2748,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -3378,6 +3058,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -3387,6 +3068,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -3704,6 +3390,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -3713,6 +3400,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -4036,6 +3728,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -4045,6 +3738,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -4070,7 +3768,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -4229,7 +3927,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -4709,6 +4407,7 @@ } }, "required": [ + "asset_type", "url", "response_type", "security" @@ -4720,6 +4419,11 @@ "description": "CSS stylesheet asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "CSS content" @@ -5014,6 +4718,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5021,371 +4726,379 @@ { "title": "DAAST Asset", "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + }, + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", + "type": "string", + "enum": [ + "1.0", + "1.1" + ] + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating DAAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" + "required": [ + "name" + ], + "additionalProperties": true }, - "transcript_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating DAAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns DAAST XML" + } + }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -5395,363 +5108,29 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -5777,6 +5156,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5784,6 +5164,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -5977,6 +5368,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -6450,7 +5852,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -7075,11 +6480,13 @@ "updated_date": "2026-02-20T09:30:00Z", "assets": { "banner_image": { + "asset_type": "image", "url": "https://cdn.example.com/holiday_300x250.png", "width": 300, "height": 250 }, "clickthrough_url": { + "asset_type": "url", "url": "https://acmecorp.example.com/holiday-sale" } }, @@ -7119,11 +6526,13 @@ "updated_date": "2026-02-20T09:35:00Z", "assets": { "banner_image": { + "asset_type": "image", "url": "https://cdn.example.com/holiday_728x90.png", "width": 728, "height": 90 }, "clickthrough_url": { + "asset_type": "url", "url": "https://acmecorp.example.com/holiday-sale" } }, @@ -7150,7 +6559,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.435Z", + "generatedAt": "2026-04-22T04:00:56.724Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/creative/preview-creative-request.json b/schemas/cache/bundled/creative/preview-creative-request.json index 0f4baa2a3..f582a3f7c 100644 --- a/schemas/cache/bundled/creative/preview-creative-request.json +++ b/schemas/cache/bundled/creative/preview-creative-request.json @@ -72,15 +72,20 @@ }, "assets": { "type": "object", - "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance \u2014 each asset must match at least one valid asset type schema.", + "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -391,6 +396,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -402,6 +408,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -868,6 +879,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -879,6 +891,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -1230,6 +1247,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -1237,389 +1255,397 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { + "jurisdictions": { + "type": "array", + "description": "Jurisdictions where disclosure obligations apply", + "items": { + "type": "object", + "properties": { + "country": { + "type": "string", + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" + }, + "region": { + "type": "string", + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + }, + "regulation": { + "type": "string", + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + }, + "label_text": { + "type": "string", + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true }, - "render_guidance": { + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, "additionalProperties": true } }, - "required": [ - "country", - "regulation" - ], "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -1629,434 +1655,82 @@ "content": { "type": "string", "description": "Inline VAST XML content" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + } + }, + "required": [ + "delivery_type", + "content" + ] + } + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true + }, + { + "title": "Text Asset", + "description": "Text content asset", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "Language code (e.g., 'en', 'es', 'fr')" + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "type": "object", + "properties": { + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "ai_tool": { "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "name": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "content" - ], - "additionalProperties": true - } - ] - }, - { - "title": "Text Asset", - "description": "Text content asset", - "type": "object", - "properties": { - "content": { - "type": "string", - "description": "Text content" - }, - "language": { - "type": "string", - "description": "Language code (e.g., 'en', 'es', 'fr')" - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { + "provider": { "type": "string", "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" } @@ -2298,6 +1972,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -2307,10 +1982,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -2612,6 +2292,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -2621,6 +2302,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -2938,6 +2624,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -2947,6 +2634,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -3270,6 +2962,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -3279,6 +2972,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -3304,7 +3002,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -3463,7 +3161,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -3943,6 +3641,7 @@ } }, "required": [ + "asset_type", "url", "response_type", "security" @@ -3954,6 +3653,11 @@ "description": "CSS stylesheet asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "CSS content" @@ -4248,6 +3952,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -4255,371 +3960,379 @@ { "title": "DAAST Asset", "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + }, + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", + "type": "string", + "enum": [ + "1.0", + "1.1" + ] + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating DAAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "ai_tool": { "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "name": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } + }, + "required": [ + "name" + ], + "additionalProperties": true + }, + "human_oversight": { + "type": "string", + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } + }, + "declared_by": { + "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], "additionalProperties": true - } - }, - "required": [ + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating DAAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns DAAST XML" + } + }, + "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -4629,363 +4342,29 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -5011,6 +4390,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5018,6 +4398,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -5211,6 +4602,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -5684,7 +5086,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -6390,15 +5795,20 @@ }, "assets": { "type": "object", - "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance \u2014 each asset must match at least one valid asset type schema.", + "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -6709,6 +6119,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -6720,6 +6131,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -7186,6 +6602,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -7197,6 +6614,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -7548,6 +6970,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -7555,389 +6978,397 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "type": "object", + "properties": { + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "required": [ + "country", + "regulation" + ], + "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -7947,466 +7378,114 @@ "content": { "type": "string", "description": "Inline VAST XML content" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + } + }, + "required": [ + "delivery_type", + "content" + ] + } + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true + }, + { + "title": "Text Asset", + "description": "Text content asset", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "Language code (e.g., 'en', 'es', 'fr')" + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "type": "object", + "properties": { + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "content" - ], - "additionalProperties": true - } - ] - }, - { - "title": "Text Asset", - "description": "Text content asset", - "type": "object", - "properties": { - "content": { - "type": "string", - "description": "Text content" - }, - "language": { - "type": "string", - "description": "Language code (e.g., 'en', 'es', 'fr')" - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { + "agent_url": { "type": "string", "format": "uri", "description": "URL of the agent or service that declared this provenance" @@ -8616,6 +7695,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -8625,10 +7705,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -8930,6 +8015,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -8939,6 +8025,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -9256,6 +8347,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -9265,6 +8357,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -9588,6 +8685,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -9597,6 +8695,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -9622,7 +8725,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -9781,7 +8884,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -9966,14 +9069,325 @@ "type": "string", "description": "Header name for HMAC signature (e.g., 'X-Signature')" }, - "api_key_header": { - "type": "string", - "description": "Header name for API key (e.g., 'X-API-Key')" + "api_key_header": { + "type": "string", + "description": "Header name for API key (e.g., 'X-API-Key')" + } + }, + "required": [ + "method" + ] + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "type": "object", + "properties": { + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", + "type": "string", + "enum": [ + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } + }, + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } + }, + "required": [ + "name" + ], + "additionalProperties": true + }, + "human_oversight": { + "type": "string", + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } + }, + "declared_by": { + "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent or service that declared this provenance" + }, + "role": { + "type": "string", + "enum": [ + "creator", + "advertiser", + "agency", + "platform", + "tool" + ], + "description": "Role of the declaring party in the supply chain", + "enumDescriptions": { + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" + } + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { + "type": "string", + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" + }, + "jurisdictions": { + "type": "array", + "description": "Jurisdictions where disclosure obligations apply", + "items": { + "type": "object", + "properties": { + "country": { + "type": "string", + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" + }, + "region": { + "type": "string", + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + }, + "regulation": { + "type": "string", + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + }, + "label_text": { + "type": "string", + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "required": [ + "country", + "regulation" + ], + "additionalProperties": true + }, + "minItems": 1 + } + }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true } }, - "required": [ - "method" - ] + "additionalProperties": true + } + }, + "required": [ + "asset_type", + "url", + "response_type", + "security" + ], + "additionalProperties": true + }, + { + "title": "CSS Asset", + "description": "CSS stylesheet asset", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, + "content": { + "type": "string", + "description": "CSS content" + }, + "media": { + "type": "string", + "description": "CSS media query context (e.g., 'screen', 'print')" }, "provenance": { "title": "Provenance", @@ -10261,24 +9675,78 @@ } }, "required": [ - "url", - "response_type", - "security" + "asset_type", + "content" ], "additionalProperties": true }, { - "title": "CSS Asset", - "description": "CSS stylesheet asset", + "title": "DAAST Asset", + "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", "type": "object", "properties": { - "content": { + "asset_type": { "type": "string", - "description": "CSS content" + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." }, - "media": { + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", "type": "string", - "description": "CSS media query context (e.g., 'screen', 'print')" + "enum": [ + "1.0", + "1.1" + ] + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true }, "provenance": { "title": "Provenance", @@ -10497,447 +9965,97 @@ } }, "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "content" - ], - "additionalProperties": true - }, - { - "title": "DAAST Asset", - "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", - "oneOf": [ - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating DAAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating DAAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns DAAST XML" + } + }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -10947,363 +10065,29 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -11329,6 +10113,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -11336,6 +10121,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -11529,6 +10325,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -12002,7 +10809,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -12637,7 +11447,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.454Z", + "generatedAt": "2026-04-22T04:00:56.741Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/creative/preview-creative-response.json b/schemas/cache/bundled/creative/preview-creative-response.json index 0dff2969f..880d17f1a 100644 --- a/schemas/cache/bundled/creative/preview-creative-response.json +++ b/schemas/cache/bundled/creative/preview-creative-response.json @@ -1051,15 +1051,20 @@ }, "assets": { "type": "object", - "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance \u2014 each asset must match at least one valid asset type schema.", + "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -1370,6 +1375,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -1381,6 +1387,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -1847,6 +1858,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -1858,6 +1870,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -2209,6 +2226,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -2216,773 +2234,429 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "url" - ], - "additionalProperties": true - }, - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "inline", - "description": "Discriminator indicating VAST is delivered as inline XML content" - }, - "content": { - "type": "string", - "description": "Inline VAST XML content" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", - "type": "string", - "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true }, - "render_guidance": { + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, "additionalProperties": true } }, - "required": [ - "country", - "regulation" - ], "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, + "required": [ + "delivery_type", + "url" + ] + }, + { + "properties": { + "delivery_type": { + "type": "string", + "const": "inline", + "description": "Discriminator indicating VAST is delivered as inline XML content" + }, + "content": { + "type": "string", + "description": "Inline VAST XML content" + } + }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Text Asset", "description": "Text content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Text content" @@ -3277,6 +2951,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -3286,10 +2961,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -3591,6 +3271,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -3600,6 +3281,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -3917,6 +3603,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -3926,7 +3613,12 @@ "description": "JavaScript code asset", "type": "object", "properties": { - "content": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, + "content": { "type": "string", "description": "JavaScript content" }, @@ -4249,6 +3941,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -4258,6 +3951,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -4283,7 +3981,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -4442,7 +4140,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -4922,6 +4620,7 @@ } }, "required": [ + "asset_type", "url", "response_type", "security" @@ -4933,13 +4632,377 @@ "description": "CSS stylesheet asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "CSS content" }, - "media": { + "media": { + "type": "string", + "description": "CSS media query context (e.g., 'screen', 'print')" + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "type": "object", + "properties": { + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", + "type": "string", + "enum": [ + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } + }, + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } + }, + "required": [ + "name" + ], + "additionalProperties": true + }, + "human_oversight": { + "type": "string", + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } + }, + "declared_by": { + "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent or service that declared this provenance" + }, + "role": { + "type": "string", + "enum": [ + "creator", + "advertiser", + "agency", + "platform", + "tool" + ], + "description": "Role of the declaring party in the supply chain", + "enumDescriptions": { + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" + } + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { + "type": "string", + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" + }, + "jurisdictions": { + "type": "array", + "description": "Jurisdictions where disclosure obligations apply", + "items": { + "type": "object", + "properties": { + "country": { + "type": "string", + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" + }, + "region": { + "type": "string", + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + }, + "regulation": { + "type": "string", + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + }, + "label_text": { + "type": "string", + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "required": [ + "country", + "regulation" + ], + "additionalProperties": true + }, + "minItems": 1 + } + }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "required": [ + "asset_type", + "content" + ], + "additionalProperties": true + }, + { + "title": "DAAST Asset", + "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + }, + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", + "type": "string", + "enum": [ + "1.0", + "1.1" + ] + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { "type": "string", - "description": "CSS media query context (e.g., 'screen', 'print')" + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true }, "provenance": { "title": "Provenance", @@ -5227,16 +5290,10 @@ } }, "required": [ - "content" + "asset_type" ], - "additionalProperties": true - }, - { - "title": "DAAST Asset", - "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", "oneOf": [ { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -5247,358 +5304,14 @@ "type": "string", "format": "uri", "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -5608,363 +5321,29 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -5990,6 +5369,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5997,6 +5377,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -6190,6 +5581,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -6663,7 +6065,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -7184,7 +6589,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.469Z", + "generatedAt": "2026-04-22T04:00:56.754Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/creative/sync-creatives-request.json b/schemas/cache/bundled/creative/sync-creatives-request.json index dce4105d1..1f75d7243 100644 --- a/schemas/cache/bundled/creative/sync-creatives-request.json +++ b/schemas/cache/bundled/creative/sync-creatives-request.json @@ -225,15 +225,20 @@ }, "assets": { "type": "object", - "description": "Assets required by the format, keyed by asset_id", + "description": "Assets required by the format, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -544,6 +549,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -555,6 +561,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -1021,6 +1032,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -1032,6 +1044,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -1383,6 +1400,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -1390,773 +1408,429 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "url" - ], - "additionalProperties": true - }, - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "inline", - "description": "Discriminator indicating VAST is delivered as inline XML content" - }, - "content": { - "type": "string", - "description": "Inline VAST XML content" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", - "type": "string", - "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true }, - "render_guidance": { + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, "additionalProperties": true } }, - "required": [ - "country", - "regulation" - ], "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, + "required": [ + "delivery_type", + "url" + ] + }, + { + "properties": { + "delivery_type": { + "type": "string", + "const": "inline", + "description": "Discriminator indicating VAST is delivered as inline XML content" + }, + "content": { + "type": "string", + "description": "Inline VAST XML content" + } + }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Text Asset", "description": "Text content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Text content" @@ -2451,6 +2125,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -2460,10 +2135,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -2765,6 +2445,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -2774,6 +2455,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -3091,6 +2777,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -3100,6 +2787,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -3423,6 +3115,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -3432,6 +3125,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -3457,7 +3155,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -3616,7 +3314,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -4096,6 +3794,7 @@ } }, "required": [ + "asset_type", "url", "response_type", "security" @@ -4107,6 +3806,11 @@ "description": "CSS stylesheet asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "CSS content" @@ -4401,6 +4105,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -4408,371 +4113,379 @@ { "title": "DAAST Asset", "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + }, + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", + "type": "string", + "enum": [ + "1.0", + "1.1" + ] + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating DAAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" + "required": [ + "name" + ], + "additionalProperties": true }, - "transcript_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating DAAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns DAAST XML" + } + }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -4782,363 +4495,29 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -5164,6 +4543,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5171,6 +4551,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -5364,6 +4755,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -5837,7 +5239,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -6412,6 +5817,7 @@ }, "assets": { "video": { + "asset_type": "video", "url": "https://cdn.example.com/hero-video.mp4", "width": 1920, "height": 1080, @@ -6453,10 +5859,12 @@ }, "assets": { "product_catalog": { + "asset_type": "catalog", "type": "product", "catalog_id": "winter-products" }, "generation_prompt": { + "asset_type": "text", "content": "Create a warm, festive holiday campaign featuring winter products" } }, @@ -6489,6 +5897,7 @@ }, "assets": { "video": { + "asset_type": "video", "url": "https://cdn.example.com/updated-hero.mp4", "width": 1920, "height": 1080, @@ -6505,6 +5914,7 @@ }, "assets": { "image": { + "asset_type": "image", "url": "https://cdn.example.com/updated-banner.png", "width": 300, "height": 250 @@ -6516,7 +5926,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.480Z", + "generatedAt": "2026-04-22T04:00:56.763Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/creative/sync-creatives-response.json b/schemas/cache/bundled/creative/sync-creatives-response.json index fef025b2a..ff8533fa0 100644 --- a/schemas/cache/bundled/creative/sync-creatives-response.json +++ b/schemas/cache/bundled/creative/sync-creatives-response.json @@ -1117,7 +1117,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.483Z", + "generatedAt": "2026-04-22T04:00:56.766Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/build-creative-request.json b/schemas/cache/bundled/media-buy/build-creative-request.json index 7d2d2d358..2a6403f03 100644 --- a/schemas/cache/bundled/media-buy/build-creative-request.json +++ b/schemas/cache/bundled/media-buy/build-creative-request.json @@ -68,15 +68,20 @@ }, "assets": { "type": "object", - "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance \u2014 each asset must match at least one valid asset type schema.", + "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -387,6 +392,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -398,6 +404,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -864,6 +875,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -875,6 +887,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -1226,6 +1243,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -1233,773 +1251,429 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "url" - ], - "additionalProperties": true - }, - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "inline", - "description": "Discriminator indicating VAST is delivered as inline XML content" - }, - "content": { - "type": "string", - "description": "Inline VAST XML content" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", - "type": "string", - "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true }, - "render_guidance": { + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, "additionalProperties": true } }, - "required": [ - "country", - "regulation" - ], "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, + "required": [ + "delivery_type", + "url" + ] + }, + { + "properties": { + "delivery_type": { + "type": "string", + "const": "inline", + "description": "Discriminator indicating VAST is delivered as inline XML content" + }, + "content": { + "type": "string", + "description": "Inline VAST XML content" + } + }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Text Asset", "description": "Text content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Text content" @@ -2294,6 +1968,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -2303,10 +1978,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -2608,6 +2288,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -2617,6 +2298,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -2934,6 +2620,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -2943,6 +2630,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -3266,6 +2958,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -3275,6 +2968,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -3300,7 +2998,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -3459,7 +3157,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -3939,6 +3637,7 @@ } }, "required": [ + "asset_type", "url", "response_type", "security" @@ -3950,6 +3649,11 @@ "description": "CSS stylesheet asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "CSS content" @@ -4244,6 +3948,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -4251,371 +3956,379 @@ { "title": "DAAST Asset", "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + }, + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", + "type": "string", + "enum": [ + "1.0", + "1.1" + ] + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating DAAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" + "required": [ + "name" + ], + "additionalProperties": true }, - "transcript_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating DAAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns DAAST XML" + } + }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -4625,363 +4338,29 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -5007,6 +4386,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5014,6 +4394,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -5207,6 +4598,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -5680,7 +5082,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -6629,7 +6034,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.491Z", + "generatedAt": "2026-04-22T04:00:56.773Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/build-creative-response.json b/schemas/cache/bundled/media-buy/build-creative-response.json index 3f0a0d5a8..39f6d1e97 100644 --- a/schemas/cache/bundled/media-buy/build-creative-response.json +++ b/schemas/cache/bundled/media-buy/build-creative-response.json @@ -62,15 +62,20 @@ }, "assets": { "type": "object", - "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance \u2014 each asset must match at least one valid asset type schema.", + "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -381,6 +386,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -392,6 +398,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -858,6 +869,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -869,6 +881,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -1220,6 +1237,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -1227,389 +1245,397 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { + "jurisdictions": { + "type": "array", + "description": "Jurisdictions where disclosure obligations apply", + "items": { + "type": "object", + "properties": { + "country": { + "type": "string", + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" + }, + "region": { + "type": "string", + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + }, + "regulation": { + "type": "string", + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + }, + "label_text": { + "type": "string", + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true }, - "render_guidance": { + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, "additionalProperties": true } }, - "required": [ - "country", - "regulation" - ], "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -1619,428 +1645,76 @@ "content": { "type": "string", "description": "Inline VAST XML content" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + } + }, + "required": [ + "delivery_type", + "content" + ] + } + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true + }, + { + "title": "Text Asset", + "description": "Text content asset", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "Language code (e.g., 'en', 'es', 'fr')" + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "type": "object", + "properties": { + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "ai_tool": { "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "name": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "content" - ], - "additionalProperties": true - } - ] - }, - { - "title": "Text Asset", - "description": "Text content asset", - "type": "object", - "properties": { - "content": { - "type": "string", - "description": "Text content" - }, - "language": { - "type": "string", - "description": "Language code (e.g., 'en', 'es', 'fr')" - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" }, "version": { "type": "string", @@ -2288,6 +1962,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -2297,10 +1972,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -2602,6 +2282,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -2611,6 +2292,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -2928,6 +2614,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -2937,6 +2624,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -3260,6 +2952,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -3269,6 +2962,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -3294,7 +2992,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -3453,7 +3151,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -3933,6 +3631,7 @@ } }, "required": [ + "asset_type", "url", "response_type", "security" @@ -3944,6 +3643,11 @@ "description": "CSS stylesheet asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "CSS content" @@ -4238,6 +3942,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -4245,371 +3950,379 @@ { "title": "DAAST Asset", "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + }, + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", + "type": "string", + "enum": [ + "1.0", + "1.1" + ] + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating DAAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "transcript_url": { + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } + }, + "required": [ + "name" + ], + "additionalProperties": true + }, + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, - "additionalProperties": true + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating DAAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns DAAST XML" } }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -4619,363 +4332,29 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -5001,6 +4380,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5008,6 +4388,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -5201,6 +4592,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -5674,7 +5076,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -6640,15 +6045,20 @@ }, "assets": { "type": "object", - "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance \u2014 each asset must match at least one valid asset type schema.", + "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -6959,6 +6369,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -6970,6 +6381,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -7436,6 +6852,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -7447,6 +6864,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -7798,6 +7220,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -7805,389 +7228,397 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "type": "object", + "properties": { + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -8197,432 +7628,80 @@ "content": { "type": "string", "description": "Inline VAST XML content" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + } + }, + "required": [ + "delivery_type", + "content" + ] + } + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true + }, + { + "title": "Text Asset", + "description": "Text content asset", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "Language code (e.g., 'en', 'es', 'fr')" + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "type": "object", + "properties": { + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "ai_tool": { "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "name": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" }, - "human_oversight": { + "version": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "content" - ], - "additionalProperties": true - } - ] - }, - { - "title": "Text Asset", - "description": "Text content asset", - "type": "object", - "properties": { - "content": { - "type": "string", - "description": "Text content" - }, - "language": { - "type": "string", - "description": "Language code (e.g., 'en', 'es', 'fr')" - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." }, "provider": { "type": "string", @@ -8866,6 +7945,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -8875,10 +7955,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -9180,6 +8265,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -9189,6 +8275,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -9506,6 +8597,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -9515,6 +8607,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -9838,6 +8935,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -9847,6 +8945,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -9872,7 +8975,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -10031,7 +9134,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -10511,24 +9614,389 @@ } }, "required": [ - "url", - "response_type", - "security" + "asset_type", + "url", + "response_type", + "security" + ], + "additionalProperties": true + }, + { + "title": "CSS Asset", + "description": "CSS stylesheet asset", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, + "content": { + "type": "string", + "description": "CSS content" + }, + "media": { + "type": "string", + "description": "CSS media query context (e.g., 'screen', 'print')" + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "type": "object", + "properties": { + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", + "type": "string", + "enum": [ + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } + }, + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } + }, + "required": [ + "name" + ], + "additionalProperties": true + }, + "human_oversight": { + "type": "string", + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } + }, + "declared_by": { + "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent or service that declared this provenance" + }, + "role": { + "type": "string", + "enum": [ + "creator", + "advertiser", + "agency", + "platform", + "tool" + ], + "description": "Role of the declaring party in the supply chain", + "enumDescriptions": { + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" + } + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { + "type": "string", + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" + }, + "jurisdictions": { + "type": "array", + "description": "Jurisdictions where disclosure obligations apply", + "items": { + "type": "object", + "properties": { + "country": { + "type": "string", + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" + }, + "region": { + "type": "string", + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + }, + "regulation": { + "type": "string", + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + }, + "label_text": { + "type": "string", + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "required": [ + "country", + "regulation" + ], + "additionalProperties": true + }, + "minItems": 1 + } + }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "required": [ + "asset_type", + "content" ], "additionalProperties": true }, { - "title": "CSS Asset", - "description": "CSS stylesheet asset", + "title": "DAAST Asset", + "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", "type": "object", "properties": { - "content": { + "asset_type": { "type": "string", - "description": "CSS content" + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." }, - "media": { + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", "type": "string", - "description": "CSS media query context (e.g., 'screen', 'print')" + "enum": [ + "1.0", + "1.1" + ] + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true }, "provenance": { "title": "Provenance", @@ -10738,456 +10206,106 @@ }, "ext": { "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "content" - ], - "additionalProperties": true - }, - { - "title": "DAAST Asset", - "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", - "oneOf": [ - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating DAAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating DAAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns DAAST XML" + } + }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -11197,363 +10315,29 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -11579,6 +10363,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -11586,6 +10371,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -11779,6 +10575,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -12252,7 +11059,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -13288,7 +12098,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.508Z", + "generatedAt": "2026-04-22T04:00:56.788Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/create-media-buy-request.json b/schemas/cache/bundled/media-buy/create-media-buy-request.json index 3b39332c5..b9d800d84 100644 --- a/schemas/cache/bundled/media-buy/create-media-buy-request.json +++ b/schemas/cache/bundled/media-buy/create-media-buy-request.json @@ -2519,15 +2519,20 @@ }, "assets": { "type": "object", - "description": "Assets required by the format, keyed by asset_id", + "description": "Assets required by the format, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -2838,6 +2843,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -2849,6 +2855,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -3315,6 +3326,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -3326,6 +3338,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -3677,6 +3694,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -3684,773 +3702,429 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "url" - ], - "additionalProperties": true - }, - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "inline", - "description": "Discriminator indicating VAST is delivered as inline XML content" - }, - "content": { - "type": "string", - "description": "Inline VAST XML content" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", - "type": "string", - "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true }, - "render_guidance": { + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, "additionalProperties": true } }, - "required": [ - "country", - "regulation" - ], "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, + "required": [ + "delivery_type", + "url" + ] + }, + { + "properties": { + "delivery_type": { + "type": "string", + "const": "inline", + "description": "Discriminator indicating VAST is delivered as inline XML content" + }, + "content": { + "type": "string", + "description": "Inline VAST XML content" + } + }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Text Asset", "description": "Text content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Text content" @@ -4745,6 +4419,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -4754,10 +4429,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -5059,6 +4739,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -5068,6 +4749,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -5385,6 +5071,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5394,6 +5081,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -5717,6 +5409,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5726,6 +5419,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -5751,7 +5449,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -5910,7 +5608,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -6390,6 +6088,7 @@ } }, "required": [ + "asset_type", "url", "response_type", "security" @@ -6401,6 +6100,11 @@ "description": "CSS stylesheet asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "CSS content" @@ -6695,6 +6399,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -6702,371 +6407,379 @@ { "title": "DAAST Asset", "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + }, + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", + "type": "string", + "enum": [ + "1.0", + "1.1" + ] + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating DAAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" + "required": [ + "name" + ], + "additionalProperties": true }, - "transcript_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating DAAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns DAAST XML" } }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -7076,363 +6789,29 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -7458,6 +6837,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -7465,6 +6845,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -7658,6 +7049,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -8131,7 +7533,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -9346,7 +8751,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.528Z", + "generatedAt": "2026-04-22T04:00:56.803Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/create-media-buy-response.json b/schemas/cache/bundled/media-buy/create-media-buy-response.json index c04b545a0..d44ed0025 100644 --- a/schemas/cache/bundled/media-buy/create-media-buy-response.json +++ b/schemas/cache/bundled/media-buy/create-media-buy-response.json @@ -4246,7 +4246,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.536Z", + "generatedAt": "2026-04-22T04:00:56.813Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/get-media-buy-delivery-request.json b/schemas/cache/bundled/media-buy/get-media-buy-delivery-request.json index 84f021437..ee65f7be7 100644 --- a/schemas/cache/bundled/media-buy/get-media-buy-delivery-request.json +++ b/schemas/cache/bundled/media-buy/get-media-buy-delivery-request.json @@ -607,7 +607,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.538Z", + "generatedAt": "2026-04-22T04:00:56.816Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/get-media-buy-delivery-response.json b/schemas/cache/bundled/media-buy/get-media-buy-delivery-response.json index 2a257c450..76a9cc7bf 100644 --- a/schemas/cache/bundled/media-buy/get-media-buy-delivery-response.json +++ b/schemas/cache/bundled/media-buy/get-media-buy-delivery-response.json @@ -5294,7 +5294,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.544Z", + "generatedAt": "2026-04-22T04:00:56.820Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/get-media-buys-request.json b/schemas/cache/bundled/media-buy/get-media-buys-request.json index ba023f268..9f817cb1d 100644 --- a/schemas/cache/bundled/media-buy/get-media-buys-request.json +++ b/schemas/cache/bundled/media-buy/get-media-buys-request.json @@ -269,7 +269,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.547Z", + "generatedAt": "2026-04-22T04:00:56.822Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/get-media-buys-response.json b/schemas/cache/bundled/media-buy/get-media-buys-response.json index 52d4a2ca1..e8c1a3b75 100644 --- a/schemas/cache/bundled/media-buy/get-media-buys-response.json +++ b/schemas/cache/bundled/media-buy/get-media-buys-response.json @@ -2342,7 +2342,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.550Z", + "generatedAt": "2026-04-22T04:00:56.825Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/get-products-request.json b/schemas/cache/bundled/media-buy/get-products-request.json index 678af3be0..3f8e394aa 100644 --- a/schemas/cache/bundled/media-buy/get-products-request.json +++ b/schemas/cache/bundled/media-buy/get-products-request.json @@ -29,6 +29,9 @@ "minItems": 1, "items": { "type": "object", + "discriminator": { + "propertyName": "scope" + }, "oneOf": [ { "properties": { @@ -56,7 +59,7 @@ "const": "product", "description": "Change scoped to a specific product." }, - "id": { + "product_id": { "type": "string", "minLength": 1, "description": "Product ID from a previous get_products response." @@ -68,7 +71,8 @@ "omit", "more_like_this" ], - "description": "'include': return this product with updated pricing and data. 'omit': exclude this product from the response. 'more_like_this': find additional products similar to this one (the original is also returned)." + "default": "include", + "description": "'include' (default): return this product with updated pricing and data. 'omit': exclude this product from the response. 'more_like_this': find additional products similar to this one (the original is also returned). Optional \u2014 when omitted, the seller treats the entry as action: 'include'." }, "ask": { "type": "string", @@ -78,8 +82,7 @@ }, "required": [ "scope", - "id", - "action" + "product_id" ], "additionalProperties": false }, @@ -90,7 +93,7 @@ "const": "proposal", "description": "Change scoped to a specific proposal." }, - "id": { + "proposal_id": { "type": "string", "minLength": 1, "description": "Proposal ID from a previous get_products response." @@ -102,7 +105,8 @@ "omit", "finalize" ], - "description": "'include': return this proposal with updated allocations and pricing. 'omit': exclude this proposal from the response. 'finalize': request firm pricing and inventory hold \u2014 transitions a draft proposal to committed with an expires_at hold window. May trigger seller-side approval (HITL). The buyer should not set a time_budget for finalize requests \u2014 they represent a commitment to wait for the result." + "default": "include", + "description": "'include' (default): return this proposal with updated allocations and pricing. 'omit': exclude this proposal from the response. 'finalize': request firm pricing and inventory hold \u2014 transitions a draft proposal to committed with an expires_at hold window. May trigger seller-side approval (HITL). The buyer should not set a time_budget for finalize requests \u2014 they represent a commitment to wait for the result. Optional \u2014 when omitted, the seller treats the entry as action: 'include'." }, "ask": { "type": "string", @@ -112,8 +116,7 @@ }, "required": [ "scope", - "id", - "action" + "proposal_id" ], "additionalProperties": false } @@ -2030,7 +2033,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.555Z", + "generatedAt": "2026-04-22T04:00:56.829Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/get-products-response.json b/schemas/cache/bundled/media-buy/get-products-response.json index c44559461..a143a1cb0 100644 --- a/schemas/cache/bundled/media-buy/get-products-response.json +++ b/schemas/cache/bundled/media-buy/get-products-response.json @@ -7111,41 +7111,105 @@ }, "refinement_applied": { "type": "array", - "description": "Seller's response to each change request in the refine array, matched by position. Each entry acknowledges whether the corresponding ask was applied, partially applied, or unable to be fulfilled. MUST contain the same number of entries in the same order as the request's refine array. Only present when the request used buying_mode: 'refine'.", + "description": "Seller's response to each change request in the refine array, matched by position. Each entry acknowledges whether the corresponding ask was applied, partially applied, or unable to be fulfilled. MUST contain the same number of entries in the same order as the request's refine array. Only present when the request used buying_mode: 'refine'. Each entry MUST echo the request entry's scope and \u2014 for product and proposal scopes \u2014 the matching id field (product_id or proposal_id), so orchestrators can cross-validate alignment.", "items": { "type": "object", - "properties": { - "scope": { - "type": "string", - "enum": [ - "request", - "product", - "proposal" + "discriminator": { + "propertyName": "scope" + }, + "oneOf": [ + { + "properties": { + "scope": { + "type": "string", + "const": "request", + "description": "Echoes scope 'request' from the corresponding refine entry." + }, + "status": { + "type": "string", + "enum": [ + "applied", + "partial", + "unable" + ], + "description": "'applied': the ask was fulfilled. 'partial': the ask was partially fulfilled \u2014 see notes for details. 'unable': the seller could not fulfill the ask \u2014 see notes for why." + }, + "notes": { + "type": "string", + "description": "Seller explanation of what was done, what couldn't be done, or why. Recommended when status is 'partial' or 'unable'." + } + }, + "required": [ + "scope", + "status" ], - "description": "Echoes the scope from the corresponding refine entry. Allows orchestrators to cross-validate alignment." - }, - "id": { - "type": "string", - "description": "Echoes the id from the corresponding refine entry (for product and proposal scopes)." + "additionalProperties": false }, - "status": { - "type": "string", - "enum": [ - "applied", - "partial", - "unable" + { + "properties": { + "scope": { + "type": "string", + "const": "product", + "description": "Echoes scope 'product' from the corresponding refine entry." + }, + "product_id": { + "type": "string", + "description": "Echoes product_id from the corresponding refine entry." + }, + "status": { + "type": "string", + "enum": [ + "applied", + "partial", + "unable" + ], + "description": "'applied': the ask was fulfilled. 'partial': the ask was partially fulfilled \u2014 see notes for details. 'unable': the seller could not fulfill the ask \u2014 see notes for why." + }, + "notes": { + "type": "string", + "description": "Seller explanation of what was done, what couldn't be done, or why. Recommended when status is 'partial' or 'unable'." + } + }, + "required": [ + "scope", + "product_id", + "status" ], - "description": "'applied': the ask was fulfilled. 'partial': the ask was partially fulfilled \u2014 see notes for details. 'unable': the seller could not fulfill the ask \u2014 see notes for why." + "additionalProperties": false }, - "notes": { - "type": "string", - "description": "Seller explanation of what was done, what couldn't be done, or why. Recommended when status is 'partial' or 'unable'." + { + "properties": { + "scope": { + "type": "string", + "const": "proposal", + "description": "Echoes scope 'proposal' from the corresponding refine entry." + }, + "proposal_id": { + "type": "string", + "description": "Echoes proposal_id from the corresponding refine entry." + }, + "status": { + "type": "string", + "enum": [ + "applied", + "partial", + "unable" + ], + "description": "'applied': the ask was fulfilled. 'partial': the ask was partially fulfilled \u2014 see notes for details. 'unable': the seller could not fulfill the ask \u2014 see notes for why." + }, + "notes": { + "type": "string", + "description": "Seller explanation of what was done, what couldn't be done, or why. Recommended when status is 'partial' or 'unable'." + } + }, + "required": [ + "scope", + "proposal_id", + "status" + ], + "additionalProperties": false } - }, - "required": [ - "status" - ], - "additionalProperties": false + ] } }, "incomplete": { @@ -7256,7 +7320,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.563Z", + "generatedAt": "2026-04-22T04:00:56.840Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/list-creative-formats-request.json b/schemas/cache/bundled/media-buy/list-creative-formats-request.json index 1af361d77..1557790ac 100644 --- a/schemas/cache/bundled/media-buy/list-creative-formats-request.json +++ b/schemas/cache/bundled/media-buy/list-creative-formats-request.json @@ -304,7 +304,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.566Z", + "generatedAt": "2026-04-22T04:00:56.843Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/list-creative-formats-response.json b/schemas/cache/bundled/media-buy/list-creative-formats-response.json index 9b0c8f229..8fe290bb1 100644 --- a/schemas/cache/bundled/media-buy/list-creative-formats-response.json +++ b/schemas/cache/bundled/media-buy/list-creative-formats-response.json @@ -4097,7 +4097,7 @@ } }, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.570Z", + "generatedAt": "2026-04-22T04:00:56.847Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/log-event-request.json b/schemas/cache/bundled/media-buy/log-event-request.json index 681f93f45..adcda5282 100644 --- a/schemas/cache/bundled/media-buy/log-event-request.json +++ b/schemas/cache/bundled/media-buy/log-event-request.json @@ -387,7 +387,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.573Z", + "generatedAt": "2026-04-22T04:00:56.849Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/log-event-response.json b/schemas/cache/bundled/media-buy/log-event-response.json index c3042fce9..2022ca986 100644 --- a/schemas/cache/bundled/media-buy/log-event-response.json +++ b/schemas/cache/bundled/media-buy/log-event-response.json @@ -186,7 +186,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.573Z", + "generatedAt": "2026-04-22T04:00:56.850Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/package-request.json b/schemas/cache/bundled/media-buy/package-request.json index bcf32d6e5..7b33cedaf 100644 --- a/schemas/cache/bundled/media-buy/package-request.json +++ b/schemas/cache/bundled/media-buy/package-request.json @@ -2319,15 +2319,20 @@ }, "assets": { "type": "object", - "description": "Assets required by the format, keyed by asset_id", + "description": "Assets required by the format, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -2638,6 +2643,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -2649,6 +2655,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -3115,6 +3126,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -3126,6 +3138,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -3477,6 +3494,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -3484,773 +3502,429 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "url" - ], - "additionalProperties": true - }, - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "inline", - "description": "Discriminator indicating VAST is delivered as inline XML content" - }, - "content": { - "type": "string", - "description": "Inline VAST XML content" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", - "type": "string", - "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true }, - "render_guidance": { + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, "additionalProperties": true } }, - "required": [ - "country", - "regulation" - ], "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, + "required": [ + "delivery_type", + "url" + ] + }, + { + "properties": { + "delivery_type": { + "type": "string", + "const": "inline", + "description": "Discriminator indicating VAST is delivered as inline XML content" + }, + "content": { + "type": "string", + "description": "Inline VAST XML content" + } + }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Text Asset", "description": "Text content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Text content" @@ -4545,6 +4219,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -4554,10 +4229,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -4859,6 +4539,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -4868,6 +4549,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -5185,6 +4871,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5194,6 +4881,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -5517,6 +5209,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5526,6 +5219,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -5551,7 +5249,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -5710,7 +5408,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -6190,6 +5888,7 @@ } }, "required": [ + "asset_type", "url", "response_type", "security" @@ -6201,6 +5900,11 @@ "description": "CSS stylesheet asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "CSS content" @@ -6495,6 +6199,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -6502,371 +6207,379 @@ { "title": "DAAST Asset", "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + }, + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", + "type": "string", + "enum": [ + "1.0", + "1.1" + ] + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating DAAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" + "required": [ + "name" + ], + "additionalProperties": true }, - "transcript_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating DAAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns DAAST XML" } }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -6876,363 +6589,29 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -7258,6 +6637,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -7265,6 +6645,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -7458,6 +6849,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -7931,7 +7333,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -8367,7 +7772,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.583Z", + "generatedAt": "2026-04-22T04:00:56.859Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/provide-performance-feedback-request.json b/schemas/cache/bundled/media-buy/provide-performance-feedback-request.json index 384762b76..ccdd6fd97 100644 --- a/schemas/cache/bundled/media-buy/provide-performance-feedback-request.json +++ b/schemas/cache/bundled/media-buy/provide-performance-feedback-request.json @@ -112,7 +112,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.586Z", + "generatedAt": "2026-04-22T04:00:56.862Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/provide-performance-feedback-response.json b/schemas/cache/bundled/media-buy/provide-performance-feedback-response.json index e9998afda..7ccefcb54 100644 --- a/schemas/cache/bundled/media-buy/provide-performance-feedback-response.json +++ b/schemas/cache/bundled/media-buy/provide-performance-feedback-response.json @@ -135,7 +135,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.586Z", + "generatedAt": "2026-04-22T04:00:56.862Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/sync-audiences-request.json b/schemas/cache/bundled/media-buy/sync-audiences-request.json index d01130b20..8bcd22cab 100644 --- a/schemas/cache/bundled/media-buy/sync-audiences-request.json +++ b/schemas/cache/bundled/media-buy/sync-audiences-request.json @@ -468,7 +468,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.587Z", + "generatedAt": "2026-04-22T04:00:56.863Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/sync-audiences-response.json b/schemas/cache/bundled/media-buy/sync-audiences-response.json index e00773b3e..ef07e0887 100644 --- a/schemas/cache/bundled/media-buy/sync-audiences-response.json +++ b/schemas/cache/bundled/media-buy/sync-audiences-response.json @@ -322,7 +322,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.588Z", + "generatedAt": "2026-04-22T04:00:56.864Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/sync-catalogs-request.json b/schemas/cache/bundled/media-buy/sync-catalogs-request.json index a2e76209b..d56147979 100644 --- a/schemas/cache/bundled/media-buy/sync-catalogs-request.json +++ b/schemas/cache/bundled/media-buy/sync-catalogs-request.json @@ -829,7 +829,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.589Z", + "generatedAt": "2026-04-22T04:00:56.865Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/sync-catalogs-response.json b/schemas/cache/bundled/media-buy/sync-catalogs-response.json index 4c56401b0..06b37a55b 100644 --- a/schemas/cache/bundled/media-buy/sync-catalogs-response.json +++ b/schemas/cache/bundled/media-buy/sync-catalogs-response.json @@ -337,7 +337,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.590Z", + "generatedAt": "2026-04-22T04:00:56.865Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/sync-event-sources-request.json b/schemas/cache/bundled/media-buy/sync-event-sources-request.json index 29e408cfc..3adb6f718 100644 --- a/schemas/cache/bundled/media-buy/sync-event-sources-request.json +++ b/schemas/cache/bundled/media-buy/sync-event-sources-request.json @@ -292,7 +292,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.591Z", + "generatedAt": "2026-04-22T04:00:56.866Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/sync-event-sources-response.json b/schemas/cache/bundled/media-buy/sync-event-sources-response.json index 2769c4e0a..225628176 100644 --- a/schemas/cache/bundled/media-buy/sync-event-sources-response.json +++ b/schemas/cache/bundled/media-buy/sync-event-sources-response.json @@ -454,7 +454,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.591Z", + "generatedAt": "2026-04-22T04:00:56.867Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/update-media-buy-request.json b/schemas/cache/bundled/media-buy/update-media-buy-request.json index b9a5bebc5..81cdd8a64 100644 --- a/schemas/cache/bundled/media-buy/update-media-buy-request.json +++ b/schemas/cache/bundled/media-buy/update-media-buy-request.json @@ -2303,15 +2303,20 @@ }, "assets": { "type": "object", - "description": "Assets required by the format, keyed by asset_id", + "description": "Assets required by the format, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -2622,6 +2627,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -2633,6 +2639,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -3099,6 +3110,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -3110,6 +3122,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -3461,6 +3478,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -3468,773 +3486,429 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "url" - ], - "additionalProperties": true - }, - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "inline", - "description": "Discriminator indicating VAST is delivered as inline XML content" - }, - "content": { - "type": "string", - "description": "Inline VAST XML content" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", - "type": "string", - "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true }, - "render_guidance": { + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, "additionalProperties": true } }, - "required": [ - "country", - "regulation" - ], "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, + "required": [ + "delivery_type", + "url" + ] + }, + { + "properties": { + "delivery_type": { + "type": "string", + "const": "inline", + "description": "Discriminator indicating VAST is delivered as inline XML content" + }, + "content": { + "type": "string", + "description": "Inline VAST XML content" + } + }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Text Asset", "description": "Text content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Text content" @@ -4529,6 +4203,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -4538,10 +4213,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -4843,6 +4523,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -4852,6 +4533,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -5169,6 +4855,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5178,6 +4865,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -5501,6 +5193,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -5510,6 +5203,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -5535,7 +5233,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -5694,7 +5392,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -6174,6 +5872,7 @@ } }, "required": [ + "asset_type", "url", "response_type", "security" @@ -6185,6 +5884,11 @@ "description": "CSS stylesheet asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "CSS content" @@ -6479,6 +6183,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -6486,737 +6191,411 @@ { "title": "DAAST Asset", "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + }, + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", + "type": "string", + "enum": [ + "1.0", + "1.1" + ] + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating DAAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" + "required": [ + "name" + ], + "additionalProperties": true }, - "transcript_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { + } + }, + "required": [ + "role" + ], + "additionalProperties": true + }, + "declared_at": { + "type": "string", + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." + }, + "created_time": { + "type": "string", + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "url" - ], - "additionalProperties": true - }, - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "inline", - "description": "Discriminator indicating DAAST is delivered as inline XML content" - }, - "content": { - "type": "string", - "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true }, - "render_guidance": { + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, "additionalProperties": true } }, - "required": [ - "country", - "regulation" - ], "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating DAAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns DAAST XML" + } + }, + "required": [ + "delivery_type", + "url" + ] + }, + { + "properties": { + "delivery_type": { + "type": "string", + "const": "inline", + "description": "Discriminator indicating DAAST is delivered as inline XML content" + }, + "content": { + "type": "string", + "description": "Inline DAAST XML content" + } + }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -7242,6 +6621,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -7249,6 +6629,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -7442,6 +6833,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -7915,7 +7317,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -10877,15 +10282,20 @@ }, "assets": { "type": "object", - "description": "Assets required by the format, keyed by asset_id", + "description": "Assets required by the format, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "title": "Image Asset", "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -11196,6 +10606,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -11207,6 +10618,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -11673,6 +11089,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" @@ -11684,6 +11101,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -12035,6 +11457,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -12042,773 +11465,429 @@ { "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", - "oneOf": [ - { + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "rewind", + "skip", + "playerExpand", + "playerCollapse", + "fullscreen", + "exitFullscreen", + "progress", + "notUsed", + "otherAdInteraction", + "interactiveStart", + "clickTracking", + "customClick", + "close", + "closeLinear", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", "type": "object", "properties": { - "delivery_type": { - "type": "string", - "const": "url", - "description": "Discriminator indicating VAST is delivered via URL endpoint" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", "type": "string", "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true + "required": [ + "name" + ], + "additionalProperties": true }, - "audio_description_url": { + "human_oversight": { "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "declared_by": { "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", + "agent_url": { "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true + "format": "uri", + "description": "URL of the agent or service that declared this provenance" }, - "human_oversight": { + "role": { "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" + "creator", + "advertiser", + "agency", + "platform", + "tool" ], + "description": "Role of the declaring party in the supply chain", "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true } }, + "required": [ + "role" + ], "additionalProperties": true - } - }, - "required": [ - "delivery_type", - "url" - ], - "additionalProperties": true - }, - { - "type": "object", - "properties": { - "delivery_type": { - "type": "string", - "const": "inline", - "description": "Discriminator indicating VAST is delivered as inline XML content" }, - "content": { + "declared_at": { "type": "string", - "description": "Inline VAST XML content" + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." }, - "vast_version": { - "title": "VAST Version", - "description": "VAST specification version", + "created_time": { "type": "string", - "enum": [ - "2.0", - "3.0", - "4.0", - "4.1", - "4.2" - ] - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" }, - "tracking_events": { - "type": "array", - "items": { - "title": "VAST Tracking Event", - "description": "Tracking events for video ads. Includes IAB VAST 4.2 TrackingEvents, plus flattened representations of Impression, Error, VideoClicks, and ViewableImpression elements. fullscreen/exitFullscreen retained for VAST 2.x/3.x compatibility. measurableImpression is an AdCP extension for MRC measurability signals.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "rewind", - "skip", - "playerExpand", - "playerCollapse", - "fullscreen", - "exitFullscreen", - "progress", - "notUsed", - "otherAdInteraction", - "interactiveStart", - "clickTracking", - "customClick", - "close", - "closeLinear", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { + "type": "string", + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true + "required": [ + "manifest_url" + ], + "additionalProperties": true }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "disclosure": { "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" }, - "verification": { + "jurisdictions": { "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, + "description": "Jurisdictions where disclosure obligations apply", "items": { "type": "object", "properties": { - "verified_by": { + "country": { "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" }, - "verified_time": { + "region": { "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" }, - "result": { + "regulation": { "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" }, - "details_url": { + "label_text": { "type": "string", - "format": "uri", - "description": "URL to the full verification report" + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true } }, "required": [ - "verified_by", - "result" + "country", + "regulation" ], "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true + }, + "minItems": 1 } }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", "additionalProperties": true } }, + "additionalProperties": true + } + }, + "required": [ + "asset_type" + ], + "oneOf": [ + { + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + } + }, + "required": [ + "delivery_type", + "url" + ] + }, + { + "properties": { + "delivery_type": { + "type": "string", + "const": "inline", + "description": "Discriminator indicating VAST is delivered as inline XML content" + }, + "content": { + "type": "string", + "description": "Inline VAST XML content" + } + }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Text Asset", "description": "Text content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Text content" @@ -13103,6 +12182,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -13112,10 +12192,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "title": "URL Asset Type", @@ -13417,6 +12502,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true @@ -13426,6 +12512,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -13743,6 +12834,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -13752,6 +12844,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -14075,6 +13172,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -14084,6 +13182,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -14109,7 +13212,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -14268,7 +13371,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "title": "Universal Macro", "description": "Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation.", @@ -14416,51 +13519,362 @@ "APP_ITEM_ID": "Mobile app identifier for the catalog item being rendered" } }, - { - "type": "string", - "description": "Custom or publisher-specific macro name" - } - ] - }, - "description": "Universal macros that must be provided for webhook to function" - }, - "response_type": { - "title": "Webhook Response Type", - "description": "Expected content type of webhook response", - "type": "string", - "enum": [ - "html", - "json", - "xml", - "javascript" - ] - }, - "security": { - "type": "object", - "description": "Security configuration for webhook calls", - "properties": { - "method": { - "title": "Webhook Security Method", - "description": "Authentication method", - "type": "string", - "enum": [ - "hmac_sha256", - "api_key", - "none" - ] + { + "type": "string", + "description": "Custom or publisher-specific macro name" + } + ] + }, + "description": "Universal macros that must be provided for webhook to function" + }, + "response_type": { + "title": "Webhook Response Type", + "description": "Expected content type of webhook response", + "type": "string", + "enum": [ + "html", + "json", + "xml", + "javascript" + ] + }, + "security": { + "type": "object", + "description": "Security configuration for webhook calls", + "properties": { + "method": { + "title": "Webhook Security Method", + "description": "Authentication method", + "type": "string", + "enum": [ + "hmac_sha256", + "api_key", + "none" + ] + }, + "hmac_header": { + "type": "string", + "description": "Header name for HMAC signature (e.g., 'X-Signature')" + }, + "api_key_header": { + "type": "string", + "description": "Header name for API key (e.g., 'X-API-Key')" + } + }, + "required": [ + "method" + ] + }, + "provenance": { + "title": "Provenance", + "description": "Provenance metadata for this asset, overrides manifest-level provenance", + "type": "object", + "properties": { + "digital_source_type": { + "title": "Digital Source Type", + "description": "IPTC-aligned classification of AI involvement in producing this content", + "type": "string", + "enum": [ + "digital_capture", + "digital_creation", + "trained_algorithmic_media", + "composite_with_trained_algorithmic_media", + "algorithmic_media", + "composite_capture", + "composite_synthetic", + "human_edits", + "data_driven_media" + ], + "enumDescriptions": { + "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", + "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", + "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", + "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", + "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", + "composite_capture": "Multiple digital captures composited together without AI", + "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", + "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", + "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" + } + }, + "ai_tool": { + "type": "object", + "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", + "properties": { + "name": { + "type": "string", + "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" + }, + "version": { + "type": "string", + "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." + }, + "provider": { + "type": "string", + "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" + } + }, + "required": [ + "name" + ], + "additionalProperties": true + }, + "human_oversight": { + "type": "string", + "description": "Level of human involvement in the AI-assisted creation process", + "enum": [ + "none", + "prompt_only", + "selected", + "edited", + "directed" + ], + "enumDescriptions": { + "none": "Fully automated with no human involvement in generation", + "prompt_only": "Human provided the prompt or instructions but did not review outputs", + "selected": "Human selected from multiple AI-generated candidates", + "edited": "Human edited or refined AI-generated output", + "directed": "Human directed the creative process with AI as an assistive tool" + } + }, + "declared_by": { + "type": "object", + "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent or service that declared this provenance" + }, + "role": { + "type": "string", + "enum": [ + "creator", + "advertiser", + "agency", + "platform", + "tool" + ], + "description": "Role of the declaring party in the supply chain", + "enumDescriptions": { + "creator": "The party that created or generated the content", + "advertiser": "The brand or advertiser that owns the content", + "agency": "Agency acting on behalf of the advertiser", + "platform": "Ad platform or publisher that processed the content", + "tool": "Automated tool or service that attached provenance metadata" + } + } + }, + "required": [ + "role" + ], + "additionalProperties": true }, - "hmac_header": { + "declared_at": { "type": "string", - "description": "Header name for HMAC signature (e.g., 'X-Signature')" + "format": "date-time", + "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." }, - "api_key_header": { + "created_time": { "type": "string", - "description": "Header name for API key (e.g., 'X-API-Key')" + "format": "date-time", + "description": "When this content was created or generated (ISO 8601)" + }, + "c2pa": { + "type": "object", + "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", + "properties": { + "manifest_url": { + "type": "string", + "format": "uri", + "description": "URL to the C2PA manifest store for this content" + } + }, + "required": [ + "manifest_url" + ], + "additionalProperties": true + }, + "disclosure": { + "type": "object", + "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", + "properties": { + "required": { + "type": "boolean", + "description": "Whether AI disclosure is required for this content based on applicable regulations" + }, + "jurisdictions": { + "type": "array", + "description": "Jurisdictions where disclosure obligations apply", + "items": { + "type": "object", + "properties": { + "country": { + "type": "string", + "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" + }, + "region": { + "type": "string", + "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" + }, + "regulation": { + "type": "string", + "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" + }, + "label_text": { + "type": "string", + "description": "Required disclosure label text for this jurisdiction, in the local language" + }, + "render_guidance": { + "type": "object", + "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", + "minProperties": 1, + "properties": { + "persistence": { + "title": "Disclosure Persistence", + "description": "How long the disclosure must persist during content playback or display", + "type": "string", + "enum": [ + "continuous", + "initial", + "flexible" + ], + "enumDescriptions": { + "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", + "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", + "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" + } + }, + "min_duration_ms": { + "type": "integer", + "minimum": 1, + "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." + }, + "positions": { + "type": "array", + "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", + "items": { + "title": "Disclosure Position", + "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", + "type": "string", + "enum": [ + "prominent", + "footer", + "audio", + "subtitle", + "overlay", + "end_card", + "pre_roll", + "companion" + ] + }, + "minItems": 1, + "uniqueItems": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "required": [ + "country", + "regulation" + ], + "additionalProperties": true + }, + "minItems": 1 + } + }, + "required": [ + "required" + ], + "additionalProperties": true + }, + "verification": { + "type": "array", + "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "verified_by": { + "type": "string", + "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" + }, + "verified_time": { + "type": "string", + "format": "date-time", + "description": "When the verification was performed (ISO 8601)" + }, + "result": { + "type": "string", + "enum": [ + "authentic", + "ai_generated", + "ai_modified", + "inconclusive" + ], + "description": "Verification outcome" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score of the verification result (0.0 to 1.0)" + }, + "details_url": { + "type": "string", + "format": "uri", + "description": "URL to the full verification report" + } + }, + "required": [ + "verified_by", + "result" + ], + "additionalProperties": true + } + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true } }, - "required": [ - "method" - ] + "additionalProperties": true + } + }, + "required": [ + "asset_type", + "url", + "response_type", + "security" + ], + "additionalProperties": true + }, + { + "title": "CSS Asset", + "description": "CSS stylesheet asset", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, + "content": { + "type": "string", + "description": "CSS content" + }, + "media": { + "type": "string", + "description": "CSS media query context (e.g., 'screen', 'print')" }, "provenance": { "title": "Provenance", @@ -14748,24 +14162,78 @@ } }, "required": [ - "url", - "response_type", - "security" + "asset_type", + "content" ], "additionalProperties": true }, { - "title": "CSS Asset", - "description": "CSS stylesheet asset", + "title": "DAAST Asset", + "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", "type": "object", "properties": { - "content": { + "asset_type": { "type": "string", - "description": "CSS content" + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + }, + "daast_version": { + "title": "DAAST Version", + "description": "DAAST specification version", + "type": "string", + "enum": [ + "1.0", + "1.1" + ] }, - "media": { + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "DAAST Tracking Event", + "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", + "type": "string", + "enum": [ + "impression", + "creativeView", + "loaded", + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "mute", + "unmute", + "pause", + "resume", + "skip", + "progress", + "clickTracking", + "customClick", + "close", + "error", + "viewable", + "notViewable", + "viewUndetermined", + "measurableImpression", + "viewableImpression" + ] + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { "type": "string", - "description": "CSS media query context (e.g., 'screen', 'print')" + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true }, "provenance": { "title": "Provenance", @@ -15053,16 +14521,10 @@ } }, "required": [ - "content" + "asset_type" ], - "additionalProperties": true - }, - { - "title": "DAAST Asset", - "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", "oneOf": [ { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -15073,358 +14535,14 @@ "type": "string", "format": "uri", "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -15434,363 +14552,29 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "title": "DAAST Version", - "description": "DAAST specification version", - "type": "string", - "enum": [ - "1.0", - "1.1" - ] - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "title": "DAAST Tracking Event", - "description": "Tracking events for audio ads. Includes DAAST-applicable events from IAB VAST/DAAST conventions, plus flattened Impression, Error, and ViewableImpression elements. creativeView included for companion ad tracking. measurableImpression is an AdCP extension.", - "type": "string", - "enum": [ - "impression", - "creativeView", - "loaded", - "start", - "firstQuartile", - "midpoint", - "thirdQuartile", - "complete", - "mute", - "unmute", - "pause", - "resume", - "skip", - "progress", - "clickTracking", - "customClick", - "close", - "error", - "viewable", - "notViewable", - "viewUndetermined", - "measurableImpression", - "viewableImpression" - ] - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "title": "Provenance", - "description": "Provenance metadata for this asset, overrides manifest-level provenance", - "type": "object", - "properties": { - "digital_source_type": { - "title": "Digital Source Type", - "description": "IPTC-aligned classification of AI involvement in producing this content", - "type": "string", - "enum": [ - "digital_capture", - "digital_creation", - "trained_algorithmic_media", - "composite_with_trained_algorithmic_media", - "algorithmic_media", - "composite_capture", - "composite_synthetic", - "human_edits", - "data_driven_media" - ], - "enumDescriptions": { - "digital_capture": "Captured by a digital device (camera, scanner, screen recording) with no AI involvement", - "digital_creation": "Created by a human using digital tools (Photoshop, Illustrator, After Effects) without AI generation", - "trained_algorithmic_media": "Generated entirely by a trained AI model (DALL-E, Midjourney, Stable Diffusion, Sora)", - "composite_with_trained_algorithmic_media": "Human-created content combined with AI-generated elements (e.g., photo with AI background)", - "algorithmic_media": "Produced by deterministic algorithms without machine learning (procedural generation, rule-based systems)", - "composite_capture": "Multiple digital captures composited together without AI", - "composite_synthetic": "Composite of multiple elements where at least one is AI-generated (e.g., stock photo composited with AI-generated background)", - "human_edits": "Content augmented, corrected, or enhanced by humans using non-generative tools", - "data_driven_media": "Assembled from structured data feeds (DCO templates, product catalogs, weather-triggered variants)" - } - }, - "ai_tool": { - "type": "object", - "description": "AI system used to generate or modify this content. Aligns with IPTC 2025.1 AI metadata fields and C2PA claim_generator.", - "properties": { - "name": { - "type": "string", - "description": "Name of the AI tool or model (e.g., 'DALL-E 3', 'Stable Diffusion XL', 'Gemini')" - }, - "version": { - "type": "string", - "description": "Version identifier for the AI tool or model (e.g., '25.1', '0125', '2.1'). For generative models, use the model version rather than the API version." - }, - "provider": { - "type": "string", - "description": "Organization that provides the AI tool (e.g., 'OpenAI', 'Stability AI', 'Google')" - } - }, - "required": [ - "name" - ], - "additionalProperties": true - }, - "human_oversight": { - "type": "string", - "description": "Level of human involvement in the AI-assisted creation process", - "enum": [ - "none", - "prompt_only", - "selected", - "edited", - "directed" - ], - "enumDescriptions": { - "none": "Fully automated with no human involvement in generation", - "prompt_only": "Human provided the prompt or instructions but did not review outputs", - "selected": "Human selected from multiple AI-generated candidates", - "edited": "Human edited or refined AI-generated output", - "directed": "Human directed the creative process with AI as an assistive tool" - } - }, - "declared_by": { - "type": "object", - "description": "Party declaring this provenance. Identifies who attached the provenance claim, enabling receiving parties to assess trust.", - "properties": { - "agent_url": { - "type": "string", - "format": "uri", - "description": "URL of the agent or service that declared this provenance" - }, - "role": { - "type": "string", - "enum": [ - "creator", - "advertiser", - "agency", - "platform", - "tool" - ], - "description": "Role of the declaring party in the supply chain", - "enumDescriptions": { - "creator": "The party that created or generated the content", - "advertiser": "The brand or advertiser that owns the content", - "agency": "Agency acting on behalf of the advertiser", - "platform": "Ad platform or publisher that processed the content", - "tool": "Automated tool or service that attached provenance metadata" - } - } - }, - "required": [ - "role" - ], - "additionalProperties": true - }, - "declared_at": { - "type": "string", - "format": "date-time", - "description": "When this provenance claim was made (ISO 8601). Distinct from created_time, which records when the content itself was produced. A provenance claim may be attached well after content creation, for example when retroactively declaring AI involvement for regulatory compliance." - }, - "created_time": { - "type": "string", - "format": "date-time", - "description": "When this content was created or generated (ISO 8601)" - }, - "c2pa": { - "type": "object", - "description": "C2PA Content Credentials reference. Links to the cryptographic provenance manifest for this content. Because file-level C2PA bindings break during ad-tech transcoding, this URL reference preserves the chain of provenance through the supply chain.", - "properties": { - "manifest_url": { - "type": "string", - "format": "uri", - "description": "URL to the C2PA manifest store for this content" - } - }, - "required": [ - "manifest_url" - ], - "additionalProperties": true - }, - "disclosure": { - "type": "object", - "description": "Regulatory disclosure requirements for this content. Indicates whether AI disclosure is required and under which jurisdictions.", - "properties": { - "required": { - "type": "boolean", - "description": "Whether AI disclosure is required for this content based on applicable regulations" - }, - "jurisdictions": { - "type": "array", - "description": "Jurisdictions where disclosure obligations apply", - "items": { - "type": "object", - "properties": { - "country": { - "type": "string", - "description": "ISO 3166-1 alpha-2 country code (e.g., 'US', 'DE', 'CN')" - }, - "region": { - "type": "string", - "description": "Sub-national region code (e.g., 'CA' for California, 'BY' for Bavaria)" - }, - "regulation": { - "type": "string", - "description": "Regulation identifier (e.g., 'eu_ai_act_article_50', 'ca_sb_942', 'cn_deep_synthesis')" - }, - "label_text": { - "type": "string", - "description": "Required disclosure label text for this jurisdiction, in the local language" - }, - "render_guidance": { - "type": "object", - "description": "How the disclosure should be rendered for this jurisdiction. Expresses the declaring party's intent for persistence and position based on regulatory requirements. Publishers control actual rendering but governance agents can audit whether guidance was followed.", - "minProperties": 1, - "properties": { - "persistence": { - "title": "Disclosure Persistence", - "description": "How long the disclosure must persist during content playback or display", - "type": "string", - "enum": [ - "continuous", - "initial", - "flexible" - ], - "enumDescriptions": { - "continuous": "Disclosure must remain visible or audible throughout the entire content display duration. For video and audio, this means the full playback duration. For static formats (display, DOOH), this means the full display slot. For DOOH specifically, 'content duration' means the ad's display slot within the rotation, not the screen's full rotation cycle.", - "initial": "Disclosure must appear at the start of content for a minimum duration before it may be removed. Pair with min_duration_ms in render_guidance or creative brief to specify the required duration.", - "flexible": "Disclosure presence is sufficient; placement timing and duration are at the publisher's discretion" - } - }, - "min_duration_ms": { - "type": "integer", - "minimum": 1, - "description": "Minimum display duration in milliseconds for initial persistence. Recommended when persistence is initial \u2014 without it, the duration is at the publisher's discretion. At serve time the publisher reads this from provenance since the brief is not available." - }, - "positions": { - "type": "array", - "description": "Preferred disclosure positions in priority order. The first position a format supports should be used.", - "items": { - "title": "Disclosure Position", - "description": "Where a required disclosure should appear within a creative. Used by creative briefs to specify disclosure placement and by formats to declare which positions they can render.", - "type": "string", - "enum": [ - "prominent", - "footer", - "audio", - "subtitle", - "overlay", - "end_card", - "pre_roll", - "companion" - ] - }, - "minItems": 1, - "uniqueItems": true - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "required": [ - "country", - "regulation" - ], - "additionalProperties": true - }, - "minItems": 1 - } - }, - "required": [ - "required" - ], - "additionalProperties": true - }, - "verification": { - "type": "array", - "description": "Third-party verification or detection results for this content. Multiple services may independently evaluate the same content. Provenance is a claim \u2014 verification results attached by the declaring party are supplementary. The enforcing party (e.g., seller/publisher) should run its own verification via get_creative_features or calibrate_content.", - "minItems": 1, - "items": { - "type": "object", - "properties": { - "verified_by": { - "type": "string", - "description": "Name of the verification service (e.g., 'DoubleVerify', 'Hive Moderation', 'Reality Defender')" - }, - "verified_time": { - "type": "string", - "format": "date-time", - "description": "When the verification was performed (ISO 8601)" - }, - "result": { - "type": "string", - "enum": [ - "authentic", - "ai_generated", - "ai_modified", - "inconclusive" - ], - "description": "Verification outcome" - }, - "confidence": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Confidence score of the verification result (0.0 to 1.0)" - }, - "details_url": { - "type": "string", - "format": "uri", - "description": "URL to the full verification report" - } - }, - "required": [ - "verified_by", - "result" - ], - "additionalProperties": true - } - }, - "ext": { - "title": "Extension Object", - "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", - "type": "object", - "additionalProperties": true - } - }, - "additionalProperties": true } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true }, { "title": "Markdown Asset", "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -15816,6 +14600,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true @@ -15823,6 +14608,17 @@ { "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Creative Brief", @@ -16016,6 +14812,17 @@ { "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "title": "Catalog", @@ -16489,7 +15296,10 @@ } ] } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -17102,7 +15912,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.608Z", + "generatedAt": "2026-04-22T04:00:56.881Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/media-buy/update-media-buy-response.json b/schemas/cache/bundled/media-buy/update-media-buy-response.json index 90bcd8bd8..f13646df2 100644 --- a/schemas/cache/bundled/media-buy/update-media-buy-response.json +++ b/schemas/cache/bundled/media-buy/update-media-buy-response.json @@ -2879,7 +2879,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.620Z", + "generatedAt": "2026-04-22T04:00:56.891Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/property/create-property-list-request.json b/schemas/cache/bundled/property/create-property-list-request.json index fae26c158..69f5a9223 100644 --- a/schemas/cache/bundled/property/create-property-list-request.json +++ b/schemas/cache/bundled/property/create-property-list-request.json @@ -705,7 +705,7 @@ ], "additionalProperties": false, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.623Z", + "generatedAt": "2026-04-22T04:00:56.893Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/property/create-property-list-response.json b/schemas/cache/bundled/property/create-property-list-response.json index 961790cab..93cc194d6 100644 --- a/schemas/cache/bundled/property/create-property-list-response.json +++ b/schemas/cache/bundled/property/create-property-list-response.json @@ -967,7 +967,7 @@ ], "additionalProperties": false, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.624Z", + "generatedAt": "2026-04-22T04:00:56.894Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/property/delete-property-list-request.json b/schemas/cache/bundled/property/delete-property-list-request.json index f3d07b838..d0a6eae72 100644 --- a/schemas/cache/bundled/property/delete-property-list-request.json +++ b/schemas/cache/bundled/property/delete-property-list-request.json @@ -191,7 +191,7 @@ ], "additionalProperties": false, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.625Z", + "generatedAt": "2026-04-22T04:00:56.895Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/property/delete-property-list-response.json b/schemas/cache/bundled/property/delete-property-list-response.json index ef767e758..3515df225 100644 --- a/schemas/cache/bundled/property/delete-property-list-response.json +++ b/schemas/cache/bundled/property/delete-property-list-response.json @@ -32,7 +32,7 @@ ], "additionalProperties": false, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.625Z", + "generatedAt": "2026-04-22T04:00:56.895Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/property/get-property-list-request.json b/schemas/cache/bundled/property/get-property-list-request.json index c594c1014..9cb0f3d2a 100644 --- a/schemas/cache/bundled/property/get-property-list-request.json +++ b/schemas/cache/bundled/property/get-property-list-request.json @@ -205,7 +205,7 @@ ], "additionalProperties": false, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.626Z", + "generatedAt": "2026-04-22T04:00:56.896Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/property/get-property-list-response.json b/schemas/cache/bundled/property/get-property-list-response.json index 9f889778a..d4d382e35 100644 --- a/schemas/cache/bundled/property/get-property-list-response.json +++ b/schemas/cache/bundled/property/get-property-list-response.json @@ -1157,7 +1157,7 @@ ], "additionalProperties": false, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.627Z", + "generatedAt": "2026-04-22T04:00:56.897Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/property/list-property-lists-request.json b/schemas/cache/bundled/property/list-property-lists-request.json index 8aefe6523..08ba4fb50 100644 --- a/schemas/cache/bundled/property/list-property-lists-request.json +++ b/schemas/cache/bundled/property/list-property-lists-request.json @@ -197,7 +197,7 @@ }, "additionalProperties": false, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.628Z", + "generatedAt": "2026-04-22T04:00:56.897Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/property/list-property-lists-response.json b/schemas/cache/bundled/property/list-property-lists-response.json index 16849d09b..f98d9c3af 100644 --- a/schemas/cache/bundled/property/list-property-lists-response.json +++ b/schemas/cache/bundled/property/list-property-lists-response.json @@ -990,7 +990,7 @@ ], "additionalProperties": false, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.629Z", + "generatedAt": "2026-04-22T04:00:56.899Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/property/update-property-list-request.json b/schemas/cache/bundled/property/update-property-list-request.json index ea55a27df..8d1a41d26 100644 --- a/schemas/cache/bundled/property/update-property-list-request.json +++ b/schemas/cache/bundled/property/update-property-list-request.json @@ -714,7 +714,7 @@ ], "additionalProperties": false, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.630Z", + "generatedAt": "2026-04-22T04:00:56.900Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/property/update-property-list-response.json b/schemas/cache/bundled/property/update-property-list-response.json index cb1aaf9c6..1821d6638 100644 --- a/schemas/cache/bundled/property/update-property-list-response.json +++ b/schemas/cache/bundled/property/update-property-list-response.json @@ -962,7 +962,7 @@ ], "additionalProperties": false, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.631Z", + "generatedAt": "2026-04-22T04:00:56.902Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/property/validate-property-delivery-request.json b/schemas/cache/bundled/property/validate-property-delivery-request.json index b03e2ba23..5ca67ef3a 100644 --- a/schemas/cache/bundled/property/validate-property-delivery-request.json +++ b/schemas/cache/bundled/property/validate-property-delivery-request.json @@ -301,7 +301,7 @@ ], "additionalProperties": false, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.632Z", + "generatedAt": "2026-04-22T04:00:56.903Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/property/validate-property-delivery-response.json b/schemas/cache/bundled/property/validate-property-delivery-response.json index 5a723cda0..86271d177 100644 --- a/schemas/cache/bundled/property/validate-property-delivery-response.json +++ b/schemas/cache/bundled/property/validate-property-delivery-response.json @@ -403,7 +403,7 @@ ], "additionalProperties": false, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.633Z", + "generatedAt": "2026-04-22T04:00:56.903Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/protocol/get-adcp-capabilities-request.json b/schemas/cache/bundled/protocol/get-adcp-capabilities-request.json index ffa41985e..0f7e2860f 100644 --- a/schemas/cache/bundled/protocol/get-adcp-capabilities-request.json +++ b/schemas/cache/bundled/protocol/get-adcp-capabilities-request.json @@ -40,7 +40,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.633Z", + "generatedAt": "2026-04-22T04:00:56.904Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/protocol/get-adcp-capabilities-response.json b/schemas/cache/bundled/protocol/get-adcp-capabilities-response.json index 34531af46..b4f1ef58a 100644 --- a/schemas/cache/bundled/protocol/get-adcp-capabilities-response.json +++ b/schemas/cache/bundled/protocol/get-adcp-capabilities-response.json @@ -1837,7 +1837,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.635Z", + "generatedAt": "2026-04-22T04:00:56.906Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/signals/activate-signal-request.json b/schemas/cache/bundled/signals/activate-signal-request.json index 87493709a..474c7a70b 100644 --- a/schemas/cache/bundled/signals/activate-signal-request.json +++ b/schemas/cache/bundled/signals/activate-signal-request.json @@ -262,7 +262,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.636Z", + "generatedAt": "2026-04-22T04:00:56.907Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/signals/activate-signal-response.json b/schemas/cache/bundled/signals/activate-signal-response.json index 24c2a3b51..59fca2562 100644 --- a/schemas/cache/bundled/signals/activate-signal-response.json +++ b/schemas/cache/bundled/signals/activate-signal-response.json @@ -313,7 +313,7 @@ } ], "_bundled": { - "generatedAt": "2026-04-21T21:56:38.637Z", + "generatedAt": "2026-04-22T04:00:56.907Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/signals/get-signals-request.json b/schemas/cache/bundled/signals/get-signals-request.json index 0c0be6f4b..0d4b8da2f 100644 --- a/schemas/cache/bundled/signals/get-signals-request.json +++ b/schemas/cache/bundled/signals/get-signals-request.json @@ -401,7 +401,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.638Z", + "generatedAt": "2026-04-22T04:00:56.908Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/signals/get-signals-response.json b/schemas/cache/bundled/signals/get-signals-response.json index 0a6a32940..aad21339c 100644 --- a/schemas/cache/bundled/signals/get-signals-response.json +++ b/schemas/cache/bundled/signals/get-signals-response.json @@ -682,7 +682,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.639Z", + "generatedAt": "2026-04-22T04:00:56.909Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/sponsored-intelligence/si-get-offering-request.json b/schemas/cache/bundled/sponsored-intelligence/si-get-offering-request.json index 8a5af1471..dc87c49ff 100644 --- a/schemas/cache/bundled/sponsored-intelligence/si-get-offering-request.json +++ b/schemas/cache/bundled/sponsored-intelligence/si-get-offering-request.json @@ -16,9 +16,15 @@ "description": "Offering identifier from the catalog to get details for", "x-entity": "offering" }, - "context": { + "intent": { "type": "string", - "description": "Optional natural language context about user intent for personalized results (e.g., 'mens size 14 near Cincinnati'). Must be anonymous - no PII." + "description": "Optional natural language description of user intent for personalized results (e.g., 'mens size 14 near Cincinnati'). Must be anonymous - no PII." + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true }, "include_products": { "type": "boolean", @@ -44,7 +50,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.639Z", + "generatedAt": "2026-04-22T04:00:56.909Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/sponsored-intelligence/si-get-offering-response.json b/schemas/cache/bundled/sponsored-intelligence/si-get-offering-response.json index a11f7e647..06f0e4fa8 100644 --- a/schemas/cache/bundled/sponsored-intelligence/si-get-offering-response.json +++ b/schemas/cache/bundled/sponsored-intelligence/si-get-offering-response.json @@ -200,7 +200,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.639Z", + "generatedAt": "2026-04-22T04:00:56.910Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/sponsored-intelligence/si-initiate-session-request.json b/schemas/cache/bundled/sponsored-intelligence/si-initiate-session-request.json index 9dc170f80..8d3ffbec2 100644 --- a/schemas/cache/bundled/sponsored-intelligence/si-initiate-session-request.json +++ b/schemas/cache/bundled/sponsored-intelligence/si-initiate-session-request.json @@ -12,9 +12,15 @@ "minimum": 1, "maximum": 99 }, - "context": { + "intent": { "type": "string", - "description": "Conversation handoff from the host describing what the user needs" + "description": "Natural language description of user intent \u2014 the conversation handoff from the host describing what the user needs from the brand agent" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true }, "identity": { "title": "SI Identity", @@ -304,12 +310,12 @@ }, "required": [ "idempotency_key", - "context", + "intent", "identity" ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.640Z", + "generatedAt": "2026-04-22T04:00:56.910Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/sponsored-intelligence/si-initiate-session-response.json b/schemas/cache/bundled/sponsored-intelligence/si-initiate-session-response.json index 4a515b0da..5066248f4 100644 --- a/schemas/cache/bundled/sponsored-intelligence/si-initiate-session-response.json +++ b/schemas/cache/bundled/sponsored-intelligence/si-initiate-session-response.json @@ -611,7 +611,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.641Z", + "generatedAt": "2026-04-22T04:00:56.911Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/sponsored-intelligence/si-send-message-request.json b/schemas/cache/bundled/sponsored-intelligence/si-send-message-request.json index 3c2dc3d57..aa218539f 100644 --- a/schemas/cache/bundled/sponsored-intelligence/si-send-message-request.json +++ b/schemas/cache/bundled/sponsored-intelligence/si-send-message-request.json @@ -74,7 +74,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.641Z", + "generatedAt": "2026-04-22T04:00:56.911Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/sponsored-intelligence/si-send-message-response.json b/schemas/cache/bundled/sponsored-intelligence/si-send-message-response.json index bde1b702d..b427d2aab 100644 --- a/schemas/cache/bundled/sponsored-intelligence/si-send-message-response.json +++ b/schemas/cache/bundled/sponsored-intelligence/si-send-message-response.json @@ -582,7 +582,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.642Z", + "generatedAt": "2026-04-22T04:00:56.912Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/sponsored-intelligence/si-terminate-session-request.json b/schemas/cache/bundled/sponsored-intelligence/si-terminate-session-request.json index 963e3a957..167d9250c 100644 --- a/schemas/cache/bundled/sponsored-intelligence/si-terminate-session-request.json +++ b/schemas/cache/bundled/sponsored-intelligence/si-terminate-session-request.json @@ -80,7 +80,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.642Z", + "generatedAt": "2026-04-22T04:00:56.912Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/bundled/sponsored-intelligence/si-terminate-session-response.json b/schemas/cache/bundled/sponsored-intelligence/si-terminate-session-response.json index e3e8c3ee4..48f27cef3 100644 --- a/schemas/cache/bundled/sponsored-intelligence/si-terminate-session-response.json +++ b/schemas/cache/bundled/sponsored-intelligence/si-terminate-session-response.json @@ -149,7 +149,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-04-21T21:56:38.642Z", + "generatedAt": "2026-04-22T04:00:56.912Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } } \ No newline at end of file diff --git a/schemas/cache/core/assets/audio-asset.json b/schemas/cache/core/assets/audio-asset.json index 12817c48c..a021db1a6 100644 --- a/schemas/cache/core/assets/audio-asset.json +++ b/schemas/cache/core/assets/audio-asset.json @@ -4,6 +4,11 @@ "description": "Audio asset with URL and technical specifications", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "audio", + "description": "Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -75,6 +80,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true diff --git a/schemas/cache/core/assets/brief-asset.json b/schemas/cache/core/assets/brief-asset.json index 8b7591454..a036f57ed 100644 --- a/schemas/cache/core/assets/brief-asset.json +++ b/schemas/cache/core/assets/brief-asset.json @@ -2,6 +2,17 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "Brief Asset", "description": "Campaign-level creative context as an asset. Carries the creative brief through the manifest so it travels with the creative through regeneration, resizing, and auditing.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "brief", + "description": "Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "$ref": "../../core/creative-brief.json" diff --git a/schemas/cache/core/assets/catalog-asset.json b/schemas/cache/core/assets/catalog-asset.json index 68e6026f7..03b8e8d4a 100644 --- a/schemas/cache/core/assets/catalog-asset.json +++ b/schemas/cache/core/assets/catalog-asset.json @@ -2,6 +2,17 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "Catalog Asset", "description": "A typed data feed as a creative asset. Carries catalog context (products, stores, jobs, etc.) within the manifest's assets map.", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "catalog", + "description": "Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + } + }, + "required": [ + "asset_type" + ], "allOf": [ { "$ref": "../../core/catalog.json" diff --git a/schemas/cache/core/assets/css-asset.json b/schemas/cache/core/assets/css-asset.json index 44e99ee8e..261ef01d8 100644 --- a/schemas/cache/core/assets/css-asset.json +++ b/schemas/cache/core/assets/css-asset.json @@ -4,6 +4,11 @@ "description": "CSS stylesheet asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "css", + "description": "Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "CSS content" @@ -18,6 +23,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true diff --git a/schemas/cache/core/assets/daast-asset.json b/schemas/cache/core/assets/daast-asset.json index 287d33dec..a6afb2e7b 100644 --- a/schemas/cache/core/assets/daast-asset.json +++ b/schemas/cache/core/assets/daast-asset.json @@ -2,9 +2,49 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "DAAST Asset", "description": "DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "daast", + "description": "Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + }, + "daast_version": { + "$ref": "../../enums/daast-version.json", + "description": "DAAST specification version" + }, + "duration_ms": { + "type": "integer", + "description": "Expected audio duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "$ref": "../../enums/daast-tracking-event.json" + }, + "description": "Tracking events supported by this DAAST tag" + }, + "companion_ads": { + "type": "boolean", + "description": "Whether companion display ads are included" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true + }, + "provenance": { + "$ref": "../../core/provenance.json", + "description": "Provenance metadata for this asset, overrides manifest-level provenance" + } + }, + "required": [ + "asset_type" + ], "oneOf": [ { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -15,46 +55,14 @@ "type": "string", "format": "uri", "description": "URL endpoint that returns DAAST XML" - }, - "daast_version": { - "$ref": "../../enums/daast-version.json", - "description": "DAAST specification version" - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "$ref": "../../enums/daast-tracking-event.json" - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "$ref": "../../core/provenance.json", - "description": "Provenance metadata for this asset, overrides manifest-level provenance" } }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -64,43 +72,16 @@ "content": { "type": "string", "description": "Inline DAAST XML content" - }, - "daast_version": { - "$ref": "../../enums/daast-version.json", - "description": "DAAST specification version" - }, - "duration_ms": { - "type": "integer", - "description": "Expected audio duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "$ref": "../../enums/daast-tracking-event.json" - }, - "description": "Tracking events supported by this DAAST tag" - }, - "companion_ads": { - "type": "boolean", - "description": "Whether companion display ads are included" - }, - "transcript_url": { - "type": "string", - "format": "uri", - "description": "URL to text transcript of the audio content", - "x-accessibility": true - }, - "provenance": { - "$ref": "../../core/provenance.json", - "description": "Provenance metadata for this asset, overrides manifest-level provenance" } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true } \ No newline at end of file diff --git a/schemas/cache/core/assets/html-asset.json b/schemas/cache/core/assets/html-asset.json index 10d9a28da..db789e149 100644 --- a/schemas/cache/core/assets/html-asset.json +++ b/schemas/cache/core/assets/html-asset.json @@ -4,6 +4,11 @@ "description": "HTML content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "html", + "description": "Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "HTML content" @@ -41,6 +46,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true diff --git a/schemas/cache/core/assets/image-asset.json b/schemas/cache/core/assets/image-asset.json index 93bc2c588..d545c140a 100644 --- a/schemas/cache/core/assets/image-asset.json +++ b/schemas/cache/core/assets/image-asset.json @@ -4,6 +4,11 @@ "description": "Image asset with URL and dimensions", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "image", + "description": "Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -34,6 +39,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" diff --git a/schemas/cache/core/assets/javascript-asset.json b/schemas/cache/core/assets/javascript-asset.json index 4c7ba560a..533992c2c 100644 --- a/schemas/cache/core/assets/javascript-asset.json +++ b/schemas/cache/core/assets/javascript-asset.json @@ -4,6 +4,11 @@ "description": "JavaScript code asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "javascript", + "description": "Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "JavaScript content" @@ -41,6 +46,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true diff --git a/schemas/cache/core/assets/markdown-asset.json b/schemas/cache/core/assets/markdown-asset.json index 7a6505660..7eb04046a 100644 --- a/schemas/cache/core/assets/markdown-asset.json +++ b/schemas/cache/core/assets/markdown-asset.json @@ -4,6 +4,11 @@ "description": "Markdown-formatted text content following CommonMark specification", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "markdown", + "description": "Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Markdown content following CommonMark spec with optional GitHub Flavored Markdown extensions" @@ -24,6 +29,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true diff --git a/schemas/cache/core/assets/text-asset.json b/schemas/cache/core/assets/text-asset.json index 75a20bb89..a03de7257 100644 --- a/schemas/cache/core/assets/text-asset.json +++ b/schemas/cache/core/assets/text-asset.json @@ -4,6 +4,11 @@ "description": "Text content asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "text", + "description": "Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + }, "content": { "type": "string", "description": "Text content" @@ -18,6 +23,7 @@ } }, "required": [ + "asset_type", "content" ], "additionalProperties": true diff --git a/schemas/cache/core/assets/url-asset.json b/schemas/cache/core/assets/url-asset.json index da65a7705..245d3b85a 100644 --- a/schemas/cache/core/assets/url-asset.json +++ b/schemas/cache/core/assets/url-asset.json @@ -4,10 +4,15 @@ "description": "URL reference asset", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "url", + "description": "Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", - "format": "uri", - "description": "URL reference" + "format": "uri-template", + "description": "URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." }, "url_type": { "$ref": "../../enums/url-asset-type.json", @@ -23,6 +28,7 @@ } }, "required": [ + "asset_type", "url" ], "additionalProperties": true diff --git a/schemas/cache/core/assets/vast-asset.json b/schemas/cache/core/assets/vast-asset.json index 0cfc85963..940864a17 100644 --- a/schemas/cache/core/assets/vast-asset.json +++ b/schemas/cache/core/assets/vast-asset.json @@ -2,9 +2,55 @@ "$schema": "http://json-schema.org/draft-07/schema#", "title": "VAST Asset", "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "type": "object", + "properties": { + "asset_type": { + "type": "string", + "const": "vast", + "description": "Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + }, + "vast_version": { + "$ref": "../../enums/vast-version.json", + "description": "VAST specification version" + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "$ref": "../../enums/vast-tracking-event.json" + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + }, + "provenance": { + "$ref": "../../core/provenance.json", + "description": "Provenance metadata for this asset, overrides manifest-level provenance" + } + }, + "required": [ + "asset_type" + ], "oneOf": [ { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -15,52 +61,14 @@ "type": "string", "format": "uri", "description": "URL endpoint that returns VAST XML" - }, - "vast_version": { - "$ref": "../../enums/vast-version.json", - "description": "VAST specification version" - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "$ref": "../../enums/vast-tracking-event.json" - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true - }, - "provenance": { - "$ref": "../../core/provenance.json", - "description": "Provenance metadata for this asset, overrides manifest-level provenance" } }, "required": [ "delivery_type", "url" - ], - "additionalProperties": true + ] }, { - "type": "object", "properties": { "delivery_type": { "type": "string", @@ -70,49 +78,16 @@ "content": { "type": "string", "description": "Inline VAST XML content" - }, - "vast_version": { - "$ref": "../../enums/vast-version.json", - "description": "VAST specification version" - }, - "vpaid_enabled": { - "type": "boolean", - "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" - }, - "duration_ms": { - "type": "integer", - "description": "Expected video duration in milliseconds (if known)", - "minimum": 0 - }, - "tracking_events": { - "type": "array", - "items": { - "$ref": "../../enums/vast-tracking-event.json" - }, - "description": "Tracking events supported by this VAST tag" - }, - "captions_url": { - "type": "string", - "format": "uri", - "description": "URL to captions file (WebVTT, SRT, etc.)", - "x-accessibility": true - }, - "audio_description_url": { - "type": "string", - "format": "uri", - "description": "URL to audio description track for visually impaired users", - "x-accessibility": true - }, - "provenance": { - "$ref": "../../core/provenance.json", - "description": "Provenance metadata for this asset, overrides manifest-level provenance" } }, "required": [ "delivery_type", "content" - ], - "additionalProperties": true + ] } - ] + ], + "discriminator": { + "propertyName": "delivery_type" + }, + "additionalProperties": true } \ No newline at end of file diff --git a/schemas/cache/core/assets/video-asset.json b/schemas/cache/core/assets/video-asset.json index ce734c34c..8a4c5dc69 100644 --- a/schemas/cache/core/assets/video-asset.json +++ b/schemas/cache/core/assets/video-asset.json @@ -4,6 +4,11 @@ "description": "Video asset with URL and technical specifications including audio track properties", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "video", + "description": "Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -190,6 +195,7 @@ } }, "required": [ + "asset_type", "url", "width", "height" diff --git a/schemas/cache/core/assets/webhook-asset.json b/schemas/cache/core/assets/webhook-asset.json index 0902e0520..64eda2b5d 100644 --- a/schemas/cache/core/assets/webhook-asset.json +++ b/schemas/cache/core/assets/webhook-asset.json @@ -4,6 +4,11 @@ "description": "Webhook for server-side dynamic content rendering (DCO)", "type": "object", "properties": { + "asset_type": { + "type": "string", + "const": "webhook", + "description": "Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + }, "url": { "type": "string", "format": "uri", @@ -24,7 +29,7 @@ "supported_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "$ref": "../../enums/universal-macro.json" }, @@ -39,7 +44,7 @@ "required_macros": { "type": "array", "items": { - "oneOf": [ + "anyOf": [ { "$ref": "../../enums/universal-macro.json" }, @@ -82,6 +87,7 @@ } }, "required": [ + "asset_type", "url", "response_type", "security" diff --git a/schemas/cache/core/creative-asset.json b/schemas/cache/core/creative-asset.json index 983b25623..bcb4d6340 100644 --- a/schemas/cache/core/creative-asset.json +++ b/schemas/cache/core/creative-asset.json @@ -19,10 +19,10 @@ }, "assets": { "type": "object", - "description": "Assets required by the format, keyed by asset_id", + "description": "Assets required by the format, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "$ref": "assets/image-asset.json" }, @@ -65,7 +65,10 @@ { "$ref": "assets/catalog-asset.json" } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true diff --git a/schemas/cache/core/creative-manifest.json b/schemas/cache/core/creative-manifest.json index d6ae87284..c51f33782 100644 --- a/schemas/cache/core/creative-manifest.json +++ b/schemas/cache/core/creative-manifest.json @@ -10,10 +10,10 @@ }, "assets": { "type": "object", - "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance \u2014 each asset must match at least one valid asset type schema.", + "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "$ref": "assets/image-asset.json" }, @@ -56,7 +56,10 @@ { "$ref": "assets/catalog-asset.json" } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true diff --git a/schemas/cache/core/offering-asset-group.json b/schemas/cache/core/offering-asset-group.json index 5c39e671b..499ff325a 100644 --- a/schemas/cache/core/offering-asset-group.json +++ b/schemas/cache/core/offering-asset-group.json @@ -14,9 +14,9 @@ }, "items": { "type": "array", - "description": "The assets in this group. Each item should match the structure for the declared asset_type. Note: JSON Schema validation accepts any valid asset structure here; enforcement that items match asset_type is the responsibility of the consuming agent.", + "description": "The assets in this group. Each item carries an `asset_type` discriminator that selects the matching asset schema. Note: the group-level `asset_type` declares the expected type; individual items must also self-tag so validators can narrow errors.", "items": { - "anyOf": [ + "oneOf": [ { "$ref": "assets/text-asset.json" }, @@ -53,7 +53,10 @@ { "$ref": "assets/webhook-asset.json" } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } }, "minItems": 1 }, @@ -75,12 +78,15 @@ "asset_type": "text", "items": [ { + "asset_type": "text", "content": "Shop the Summer Sale" }, { + "asset_type": "text", "content": "50% Off Everything" }, { + "asset_type": "text", "content": "Summer Savings Event" } ] @@ -93,11 +99,13 @@ "asset_type": "image", "items": [ { + "asset_type": "image", "url": "https://cdn.acme.com/hero.jpg", "width": 1200, "height": 628 }, { + "asset_type": "image", "url": "https://cdn.acme.com/hero2.jpg", "width": 1200, "height": 628 diff --git a/schemas/cache/core/offering.json b/schemas/cache/core/offering.json index a9b34053b..8d7033030 100644 --- a/schemas/cache/core/offering.json +++ b/schemas/cache/core/offering.json @@ -222,12 +222,15 @@ "asset_type": "text", "items": [ { + "asset_type": "text", "content": "Shop the Summer Sale" }, { + "asset_type": "text", "content": "50% Off Everything" }, { + "asset_type": "text", "content": "Summer Savings Event" } ] @@ -237,6 +240,7 @@ "asset_type": "image", "items": [ { + "asset_type": "image", "url": "https://cdn.acme.com/hero.jpg", "width": 1200, "height": 628 @@ -248,6 +252,7 @@ "asset_type": "image", "items": [ { + "asset_type": "image", "url": "https://cdn.acme.com/sq.jpg", "width": 600, "height": 600 diff --git a/schemas/cache/creative/asset-types/index.json b/schemas/cache/creative/asset-types/index.json index 2c8594569..9b6f8249c 100644 --- a/schemas/cache/creative/asset-types/index.json +++ b/schemas/cache/creative/asset-types/index.json @@ -3,7 +3,7 @@ "title": "AdCP Asset Type Registry", "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).", "version": "1.0.0", - "lastUpdated": "2026-04-21", + "lastUpdated": "2026-04-22", "asset_types": { "image": { "description": "Static image asset (JPG, PNG, GIF, WebP, SVG)", @@ -95,11 +95,18 @@ "3. For each asset in manifest, look up asset_id in format's assets array", "4. Validate asset matches the type and requirements defined in the format" ] + }, + "nested_discriminator_pattern": { + "description": "Asset schemas with internal variants (e.g., VAST and DAAST support both URL-delivery and inline XML) use a two-level discriminator rather than splitting each variant into a separate top-level asset_type. The outer discriminator (`asset_type` on the composite map) selects the asset schema; an inner `oneOf` + `discriminator` inside that schema selects the variant. Future asset types with internal variants should follow this pattern \u2014 do not introduce sibling entries like `vast_url` and `vast_inline` at the registry level.", + "examples": [ + "vast-asset.json: outer asset_type='vast', inner delivery_type='url'|'inline'", + "daast-asset.json: outer asset_type='daast', inner delivery_type='url'|'inline'" + ] } }, "usage_notes": { "format_specs": "Format specifications define what asset_ids are required (e.g., 'hero_image', 'logo'). Each defines its asset type and constraints (dimensions, file size, etc.).", - "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.", + "creative_manifests": "Creative manifests provide actual asset content, keyed by asset_id from the format. Each asset value carries an `asset_type` discriminator (one of the registry keys) so validators can select the matching asset schema and report errors against only that branch. The format specification also defines what asset_type each asset_id should have \u2014 payload and format should agree.", "example_flow": "Format says 'hero_image' must be type 'image' with width 1200, height 627. Manifest provides hero_image: {url: '...', width: 1200, height: 627}. The format spec tells us it's an image type." }, "adcp_version": "latest", diff --git a/schemas/cache/creative/list-creatives-response.json b/schemas/cache/creative/list-creatives-response.json index 39b0c1eca..931c88e8d 100644 --- a/schemas/cache/creative/list-creatives-response.json +++ b/schemas/cache/creative/list-creatives-response.json @@ -86,10 +86,10 @@ }, "assets": { "type": "object", - "description": "Assets for this creative, keyed by asset_id", + "description": "Assets for this creative, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema.", "patternProperties": { "^[a-z0-9_]+$": { - "anyOf": [ + "oneOf": [ { "$ref": "../core/assets/image-asset.json" }, @@ -132,7 +132,10 @@ { "$ref": "../core/assets/catalog-asset.json" } - ] + ], + "discriminator": { + "propertyName": "asset_type" + } } }, "additionalProperties": true @@ -365,11 +368,13 @@ "updated_date": "2026-02-20T09:30:00Z", "assets": { "banner_image": { + "asset_type": "image", "url": "https://cdn.example.com/holiday_300x250.png", "width": 300, "height": 250 }, "clickthrough_url": { + "asset_type": "url", "url": "https://acmecorp.example.com/holiday-sale" } }, @@ -409,11 +414,13 @@ "updated_date": "2026-02-20T09:35:00Z", "assets": { "banner_image": { + "asset_type": "image", "url": "https://cdn.example.com/holiday_728x90.png", "width": 728, "height": 90 }, "clickthrough_url": { + "asset_type": "url", "url": "https://acmecorp.example.com/holiday-sale" } }, diff --git a/schemas/cache/creative/sync-creatives-request.json b/schemas/cache/creative/sync-creatives-request.json index ca965c8c5..32f495162 100644 --- a/schemas/cache/creative/sync-creatives-request.json +++ b/schemas/cache/creative/sync-creatives-request.json @@ -130,6 +130,7 @@ }, "assets": { "video": { + "asset_type": "video", "url": "https://cdn.example.com/hero-video.mp4", "width": 1920, "height": 1080, @@ -171,10 +172,12 @@ }, "assets": { "product_catalog": { + "asset_type": "catalog", "type": "product", "catalog_id": "winter-products" }, "generation_prompt": { + "asset_type": "text", "content": "Create a warm, festive holiday campaign featuring winter products" } }, @@ -207,6 +210,7 @@ }, "assets": { "video": { + "asset_type": "video", "url": "https://cdn.example.com/updated-hero.mp4", "width": 1920, "height": 1080, @@ -223,6 +227,7 @@ }, "assets": { "image": { + "asset_type": "image", "url": "https://cdn.example.com/updated-banner.png", "width": 300, "height": 250 diff --git a/schemas/cache/extensions/index.json b/schemas/cache/extensions/index.json index c37fcbc45..f828d151c 100644 --- a/schemas/cache/extensions/index.json +++ b/schemas/cache/extensions/index.json @@ -3,6 +3,6 @@ "title": "AdCP Extension Registry", "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.", "_generated": true, - "_generatedAt": "2026-04-21T21:56:38.321Z", + "_generatedAt": "2026-04-22T04:00:56.617Z", "extensions": {} } \ No newline at end of file diff --git a/schemas/cache/governance/check-governance-request.json b/schemas/cache/governance/check-governance-request.json index a80773cde..1d4fc5a6c 100644 --- a/schemas/cache/governance/check-governance-request.json +++ b/schemas/cache/governance/check-governance-request.json @@ -13,7 +13,7 @@ }, "plan_id": { "type": "string", - "description": "Campaign governance plan identifier.", + "description": "Campaign governance plan identifier. The plan uniquely scopes the account and operator; do not include a separate `account` field \u2014 the governance agent resolves account from the plan. Including `account` is rejected by `additionalProperties: false`.", "x-entity": "governance_plan" }, "caller": { diff --git a/schemas/cache/governance/get-plan-audit-logs-request.json b/schemas/cache/governance/get-plan-audit-logs-request.json index 1c5fa3790..2125760b9 100644 --- a/schemas/cache/governance/get-plan-audit-logs-request.json +++ b/schemas/cache/governance/get-plan-audit-logs-request.json @@ -18,7 +18,7 @@ "x-entity": "governance_plan" }, "minItems": 1, - "description": "Plan IDs to retrieve. For a single plan, pass a one-element array." + "description": "Plan IDs to retrieve. For a single plan, pass a one-element array. Plans uniquely scope account and operator; do not include a separate `account` field \u2014 the governance agent resolves account from each plan. Including `account` is rejected by `additionalProperties: false`." }, "portfolio_plan_ids": { "type": "array", diff --git a/schemas/cache/governance/report-plan-outcome-request.json b/schemas/cache/governance/report-plan-outcome-request.json index 42e82f829..3ef2dd96d 100644 --- a/schemas/cache/governance/report-plan-outcome-request.json +++ b/schemas/cache/governance/report-plan-outcome-request.json @@ -14,7 +14,7 @@ }, "plan_id": { "type": "string", - "description": "The plan this outcome is for.", + "description": "The plan this outcome is for. The plan uniquely scopes the account and operator; do not include a separate `account` field \u2014 the governance agent resolves account from the plan. Including `account` is rejected by `additionalProperties: false`.", "x-entity": "governance_plan" }, "check_id": { diff --git a/schemas/cache/index.json b/schemas/cache/index.json index a5eec5ffb..1ff41369f 100644 --- a/schemas/cache/index.json +++ b/schemas/cache/index.json @@ -7,7 +7,7 @@ "versioning": { "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/." }, - "lastUpdated": "2026-04-21", + "lastUpdated": "2026-04-22", "baseUrl": "/schemas/latest", "schemas": { "core": { diff --git a/schemas/cache/media-buy/get-products-request.json b/schemas/cache/media-buy/get-products-request.json index ed565309d..deabb7ed9 100644 --- a/schemas/cache/media-buy/get-products-request.json +++ b/schemas/cache/media-buy/get-products-request.json @@ -29,6 +29,9 @@ "minItems": 1, "items": { "type": "object", + "discriminator": { + "propertyName": "scope" + }, "oneOf": [ { "properties": { @@ -56,7 +59,7 @@ "const": "product", "description": "Change scoped to a specific product." }, - "id": { + "product_id": { "type": "string", "minLength": 1, "description": "Product ID from a previous get_products response." @@ -68,7 +71,8 @@ "omit", "more_like_this" ], - "description": "'include': return this product with updated pricing and data. 'omit': exclude this product from the response. 'more_like_this': find additional products similar to this one (the original is also returned)." + "default": "include", + "description": "'include' (default): return this product with updated pricing and data. 'omit': exclude this product from the response. 'more_like_this': find additional products similar to this one (the original is also returned). Optional \u2014 when omitted, the seller treats the entry as action: 'include'." }, "ask": { "type": "string", @@ -78,8 +82,7 @@ }, "required": [ "scope", - "id", - "action" + "product_id" ], "additionalProperties": false }, @@ -90,7 +93,7 @@ "const": "proposal", "description": "Change scoped to a specific proposal." }, - "id": { + "proposal_id": { "type": "string", "minLength": 1, "description": "Proposal ID from a previous get_products response." @@ -102,7 +105,8 @@ "omit", "finalize" ], - "description": "'include': return this proposal with updated allocations and pricing. 'omit': exclude this proposal from the response. 'finalize': request firm pricing and inventory hold \u2014 transitions a draft proposal to committed with an expires_at hold window. May trigger seller-side approval (HITL). The buyer should not set a time_budget for finalize requests \u2014 they represent a commitment to wait for the result." + "default": "include", + "description": "'include' (default): return this proposal with updated allocations and pricing. 'omit': exclude this proposal from the response. 'finalize': request firm pricing and inventory hold \u2014 transitions a draft proposal to committed with an expires_at hold window. May trigger seller-side approval (HITL). The buyer should not set a time_budget for finalize requests \u2014 they represent a commitment to wait for the result. Optional \u2014 when omitted, the seller treats the entry as action: 'include'." }, "ask": { "type": "string", @@ -112,8 +116,7 @@ }, "required": [ "scope", - "id", - "action" + "proposal_id" ], "additionalProperties": false } diff --git a/schemas/cache/media-buy/get-products-response.json b/schemas/cache/media-buy/get-products-response.json index 1f4e0c4e5..1db075587 100644 --- a/schemas/cache/media-buy/get-products-response.json +++ b/schemas/cache/media-buy/get-products-response.json @@ -35,41 +35,105 @@ }, "refinement_applied": { "type": "array", - "description": "Seller's response to each change request in the refine array, matched by position. Each entry acknowledges whether the corresponding ask was applied, partially applied, or unable to be fulfilled. MUST contain the same number of entries in the same order as the request's refine array. Only present when the request used buying_mode: 'refine'.", + "description": "Seller's response to each change request in the refine array, matched by position. Each entry acknowledges whether the corresponding ask was applied, partially applied, or unable to be fulfilled. MUST contain the same number of entries in the same order as the request's refine array. Only present when the request used buying_mode: 'refine'. Each entry MUST echo the request entry's scope and \u2014 for product and proposal scopes \u2014 the matching id field (product_id or proposal_id), so orchestrators can cross-validate alignment.", "items": { "type": "object", - "properties": { - "scope": { - "type": "string", - "enum": [ - "request", - "product", - "proposal" + "discriminator": { + "propertyName": "scope" + }, + "oneOf": [ + { + "properties": { + "scope": { + "type": "string", + "const": "request", + "description": "Echoes scope 'request' from the corresponding refine entry." + }, + "status": { + "type": "string", + "enum": [ + "applied", + "partial", + "unable" + ], + "description": "'applied': the ask was fulfilled. 'partial': the ask was partially fulfilled \u2014 see notes for details. 'unable': the seller could not fulfill the ask \u2014 see notes for why." + }, + "notes": { + "type": "string", + "description": "Seller explanation of what was done, what couldn't be done, or why. Recommended when status is 'partial' or 'unable'." + } + }, + "required": [ + "scope", + "status" ], - "description": "Echoes the scope from the corresponding refine entry. Allows orchestrators to cross-validate alignment." - }, - "id": { - "type": "string", - "description": "Echoes the id from the corresponding refine entry (for product and proposal scopes)." + "additionalProperties": false }, - "status": { - "type": "string", - "enum": [ - "applied", - "partial", - "unable" + { + "properties": { + "scope": { + "type": "string", + "const": "product", + "description": "Echoes scope 'product' from the corresponding refine entry." + }, + "product_id": { + "type": "string", + "description": "Echoes product_id from the corresponding refine entry." + }, + "status": { + "type": "string", + "enum": [ + "applied", + "partial", + "unable" + ], + "description": "'applied': the ask was fulfilled. 'partial': the ask was partially fulfilled \u2014 see notes for details. 'unable': the seller could not fulfill the ask \u2014 see notes for why." + }, + "notes": { + "type": "string", + "description": "Seller explanation of what was done, what couldn't be done, or why. Recommended when status is 'partial' or 'unable'." + } + }, + "required": [ + "scope", + "product_id", + "status" ], - "description": "'applied': the ask was fulfilled. 'partial': the ask was partially fulfilled \u2014 see notes for details. 'unable': the seller could not fulfill the ask \u2014 see notes for why." + "additionalProperties": false }, - "notes": { - "type": "string", - "description": "Seller explanation of what was done, what couldn't be done, or why. Recommended when status is 'partial' or 'unable'." + { + "properties": { + "scope": { + "type": "string", + "const": "proposal", + "description": "Echoes scope 'proposal' from the corresponding refine entry." + }, + "proposal_id": { + "type": "string", + "description": "Echoes proposal_id from the corresponding refine entry." + }, + "status": { + "type": "string", + "enum": [ + "applied", + "partial", + "unable" + ], + "description": "'applied': the ask was fulfilled. 'partial': the ask was partially fulfilled \u2014 see notes for details. 'unable': the seller could not fulfill the ask \u2014 see notes for why." + }, + "notes": { + "type": "string", + "description": "Seller explanation of what was done, what couldn't be done, or why. Recommended when status is 'partial' or 'unable'." + } + }, + "required": [ + "scope", + "proposal_id", + "status" + ], + "additionalProperties": false } - }, - "required": [ - "status" - ], - "additionalProperties": false + ] } }, "incomplete": { diff --git a/schemas/cache/sponsored-intelligence/si-get-offering-request.json b/schemas/cache/sponsored-intelligence/si-get-offering-request.json index 3324533b4..2a879b8ff 100644 --- a/schemas/cache/sponsored-intelligence/si-get-offering-request.json +++ b/schemas/cache/sponsored-intelligence/si-get-offering-request.json @@ -16,9 +16,12 @@ "description": "Offering identifier from the catalog to get details for", "x-entity": "offering" }, - "context": { + "intent": { "type": "string", - "description": "Optional natural language context about user intent for personalized results (e.g., 'mens size 14 near Cincinnati'). Must be anonymous - no PII." + "description": "Optional natural language description of user intent for personalized results (e.g., 'mens size 14 near Cincinnati'). Must be anonymous - no PII." + }, + "context": { + "$ref": "../core/context.json" }, "include_products": { "type": "boolean", diff --git a/schemas/cache/sponsored-intelligence/si-initiate-session-request.json b/schemas/cache/sponsored-intelligence/si-initiate-session-request.json index 655d2004c..751dd6de4 100644 --- a/schemas/cache/sponsored-intelligence/si-initiate-session-request.json +++ b/schemas/cache/sponsored-intelligence/si-initiate-session-request.json @@ -12,9 +12,12 @@ "minimum": 1, "maximum": 99 }, - "context": { + "intent": { "type": "string", - "description": "Conversation handoff from the host describing what the user needs" + "description": "Natural language description of user intent \u2014 the conversation handoff from the host describing what the user needs from the brand agent" + }, + "context": { + "$ref": "../core/context.json" }, "identity": { "$ref": "si-identity.json" @@ -54,7 +57,7 @@ }, "required": [ "idempotency_key", - "context", + "intent", "identity" ], "additionalProperties": true diff --git a/scripts/post_generate_fixes.py b/scripts/post_generate_fixes.py index 2d011e8dc..134623d68 100644 --- a/scripts/post_generate_fixes.py +++ b/scripts/post_generate_fixes.py @@ -643,6 +643,162 @@ def restore_format_category_deprecation_shim(): print(f" ✓ Restored format_category deprecation shim at {rel}") +def inject_literal_discriminator_defaults() -> None: + """Inject defaults for ``Literal[]`` required fields. + + AdCP's schema marks discriminator fields like ``asset_type``, + ``delivery_type``, ``pricing_model`` as required even though the + field's type is ``Literal[]`` — the spec's intent is + "this field MUST be this one tag", not "the user MUST type the + tag out by hand". Pydantic takes the spec literally and generates + the field as required, breaking ergonomic construction:: + + # Spec-literal generated shape: + text = TextAsset(asset_type="text", content="hello") + + # With this fix: + text = TextAsset(content="hello") # asset_type defaults to "text" + + Wire consumption is unchanged — the ``Literal`` type still rejects + any value other than the tag, and validating a dict from the wire + still populates the field the same way. This only affects + in-process construction ergonomics. + + The fix is pattern-based: any ``AnnAssign`` whose annotation is + ``Literal['x']`` (or ``Annotated[Literal['x'], ...]``) and has no + default gets ``= 'x'`` appended. No spec-value-specific logic. + Robust to spec churn as long as the single-value-Literal pattern + holds. + """ + import ast + + total_classes = 0 + total_fields = 0 + total_files = 0 + + for py_file in sorted(OUTPUT_DIR.rglob("*.py")): + if py_file.name == "__init__.py": + continue + + source = py_file.read_text() + try: + tree = ast.parse(source) + except SyntaxError: + continue + + edits: list[tuple[int, str]] = [] # (end_lineno, literal_value) + + for node in ast.walk(tree): + if not isinstance(node, ast.ClassDef): + continue + class_has_edit = False + for stmt in node.body: + if not isinstance(stmt, ast.AnnAssign): + continue + if stmt.value is not None: + continue # already has a default + literal_value = _extract_single_literal_value(stmt.annotation) + if literal_value is None: + continue + # ast end_lineno is 1-indexed, inclusive. The annotation + # ends on that line; we want to append " = ''" at + # end of that line. + edits.append((stmt.end_lineno, literal_value)) + total_fields += 1 + class_has_edit = True + if class_has_edit: + total_classes += 1 + + if not edits: + continue + + # Apply line-based edits. Sort descending so earlier edits don't + # shift the line indices of later ones (we're editing in place + # without inserting new lines, but defensive). + lines = source.split("\n") + for end_lineno, value in sorted(edits, key=lambda e: -e[0]): + idx = end_lineno - 1 # 0-indexed + # Escape the literal value as a Python string literal. + # datamodel-codegen only emits str-valued Literals for + # discriminators in AdCP schemas; if the value isn't a str, + # skip conservatively. + if not isinstance(value, str): + continue + escaped = repr(value) + lines[idx] = f"{lines[idx]} = {escaped}" + + py_file.write_text("\n".join(lines)) + total_files += 1 + + print( + f" ✓ Injected Literal[] defaults: " + f"{total_fields} fields across {total_classes} classes in {total_files} files" + ) + + +def _extract_single_literal_value(annotation: ast.AST) -> object | None: + """Return the single Literal value if the annotation is effectively + ``Literal[X]`` (optionally wrapped in ``Annotated[...]``); else None. + + Handles both shapes datamodel-codegen emits: + + * ``Literal['text']`` — bare Literal + * ``Annotated[Literal['text'], Field(...)]`` — wrapped in Annotated + with a Field descriptor (the typical discriminator shape) + + Returns None if the annotation is a Literal with multiple values, + a Literal over non-strings, or anything else. We only want to + auto-default the unambiguous single-tag case. + """ + import ast + + # Unwrap Annotated[X, ...] → X + if isinstance(annotation, ast.Subscript) and _subscript_base_name(annotation) == "Annotated": + inner = _first_subscript_arg(annotation) + if inner is None: + return None + annotation = inner + + # Expect Literal[X] + if not isinstance(annotation, ast.Subscript): + return None + if _subscript_base_name(annotation) != "Literal": + return None + + # Extract the subscript arg(s). Single-value case only. + # ast.Subscript.slice in 3.9+ is the value directly (not a Tuple for single). + slice_node = annotation.slice + if isinstance(slice_node, ast.Tuple): + # Literal['a', 'b'] — multiple values, skip + return None + if not isinstance(slice_node, ast.Constant): + return None + return slice_node.value + + +def _subscript_base_name(node: ast.Subscript) -> str | None: + """Return the subscripted name (e.g. 'Literal' for Literal['x']).""" + import ast + + value = node.value + if isinstance(value, ast.Name): + return value.id + if isinstance(value, ast.Attribute): + return value.attr + return None + + +def _first_subscript_arg(node: ast.Subscript) -> ast.AST | None: + """Return the first argument of a subscript. For Annotated[X, ...] + this is X; for single-arg Literal[X] this is the constant node.""" + import ast + + slice_node = node.slice + if isinstance(slice_node, ast.Tuple): + return slice_node.elts[0] if slice_node.elts else None + return slice_node + + def main(): """Apply all post-generation fixes.""" print("Applying post-generation fixes...") @@ -659,6 +815,7 @@ def main(): fix_list_field_shadowing() fix_reuse_model_discriminator_bug() restore_format_category_deprecation_shim() + inject_literal_discriminator_defaults() print("\n✓ Post-generation fixes complete\n") diff --git a/src/adcp/types/_generated.py b/src/adcp/types/_generated.py index 42012d6b3..803702b34 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-04-21 22:42:50 UTC +Generation date: 2026-04-22 04:28:13 UTC """ # ruff: noqa: E501, I001 @@ -654,7 +654,7 @@ from adcp.types.generated_poc.core.media_buy import Cancellation, MediaBuy from adcp.types.generated_poc.core.media_buy_features import MediaBuyFeatures from adcp.types.generated_poc.core.offering import GeoTargets, Metro, Offering, PostalArea, Region -from adcp.types.generated_poc.core.offering_asset_group import OfferingAssetGroup +from adcp.types.generated_poc.core.offering_asset_group import Items, OfferingAssetGroup from adcp.types.generated_poc.core.optimization_goal import ( EventSource, Metric, @@ -1049,7 +1049,7 @@ ) from adcp.types.generated_poc.governance.sync_plans_response import ( ResolvedPolicy, - Status38, + Status42, SyncPlansResponse, ) from adcp.types.generated_poc.media_buy.build_creative_async_response_input_required import ( @@ -1142,12 +1142,15 @@ Refine, Refine1, Refine2, + Refine3, ) from adcp.types.generated_poc.media_buy.get_products_response import ( GetProductsResponse, IncompleteItem, - RefinementAppliedItem, - Scope3, + RefinementApplied, + RefinementApplied1, + RefinementApplied2, + RefinementApplied3, ) from adcp.types.generated_poc.media_buy.list_creative_formats_request import ( ListCreativeFormatsRequest, @@ -1299,7 +1302,7 @@ ) from adcp.types.generated_poc.property.validation_result import ( Requirement, - Status52, + Status56, ValidationResult, ) from adcp.types.generated_poc.protocol.get_adcp_capabilities_request import ( @@ -2241,7 +2244,6 @@ Disclosure135, Disclosure136, Disclosure137, - Items, Items1, Jurisdiction132, Jurisdiction133, @@ -2294,7 +2296,7 @@ RenderGuidance136, Role153, Role166, - Status22, + Status26, TrackingEvent26, Variable, VerificationItem125, @@ -2750,7 +2752,7 @@ DataSubjectContestation89, Error35, Error36, - Status34, + Status38, SyncCreativesResponse4, SyncCreativesResponse5, SyncCreativesResponse6, @@ -3391,7 +3393,8 @@ Radius11, Radius12, Refine4, - Refine5, + Refine6, + Refine7, RequiredFeatures, RequiredPerformanceStandard, SignalId9, @@ -3551,6 +3554,9 @@ Reach3, Reach4, Reach5, + RefinementApplied4, + RefinementApplied6, + RefinementApplied7, RequiredEventType, Saves, Saves1, @@ -3558,14 +3564,13 @@ Saves3, Saves4, Saves5, - Scope5, Spend2, Spend3, Spend4, Spend5, Spend6, - Status17, - Status18, + Status19, + Status20, SupportedTarget1, SupportsGeoBreakdown, Type46, @@ -4310,8 +4315,8 @@ ) from adcp.types.generated_poc.bundled.property.validate_property_delivery_response import ( Authorization, - Status49, - Status50, + Status53, + Status54, ) from adcp.types.generated_poc.bundled.protocol.get_adcp_capabilities_response import ( AvailableUs, @@ -7246,9 +7251,17 @@ "Refine", "Refine1", "Refine2", + "Refine3", "Refine4", - "Refine5", - "RefinementAppliedItem", + "Refine6", + "Refine7", + "RefinementApplied", + "RefinementApplied1", + "RefinementApplied2", + "RefinementApplied3", + "RefinementApplied4", + "RefinementApplied6", + "RefinementApplied7", "Region", "RegulatoryBasi", "RegulatoryFramework", @@ -7643,8 +7656,6 @@ "Scenario", "Scheme", "Scope", - "Scope3", - "Scope5", "Secondary", "Secondary1", "Secondary1Item", @@ -7724,14 +7735,14 @@ "Status", "Status11", "Status13", - "Status17", - "Status18", - "Status22", - "Status34", + "Status19", + "Status20", + "Status26", "Status38", - "Status49", - "Status50", - "Status52", + "Status42", + "Status53", + "Status54", + "Status56", "Status6", "StatusFilter", "StatusFilter2", diff --git a/src/adcp/types/generated_poc/a2ui/bound_value.py b/src/adcp/types/generated_poc/a2ui/bound_value.py index aee9f460e..f2db5d156 100644 --- a/src/adcp/types/generated_poc/a2ui/bound_value.py +++ b/src/adcp/types/generated_poc/a2ui/bound_value.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: a2ui/bound_value.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/a2ui/component.py b/src/adcp/types/generated_poc/a2ui/component.py index 6edec3bc1..425c4a105 100644 --- a/src/adcp/types/generated_poc/a2ui/component.py +++ b/src/adcp/types/generated_poc/a2ui/component.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: a2ui/component.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/a2ui/si_catalog.py b/src/adcp/types/generated_poc/a2ui/si_catalog.py index dae2f9bdc..d67f4912b 100644 --- a/src/adcp/types/generated_poc/a2ui/si_catalog.py +++ b/src/adcp/types/generated_poc/a2ui/si_catalog.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: a2ui/si_catalog.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/a2ui/surface.py b/src/adcp/types/generated_poc/a2ui/surface.py index 62d65dd9e..d5dab00c5 100644 --- a/src/adcp/types/generated_poc/a2ui/surface.py +++ b/src/adcp/types/generated_poc/a2ui/surface.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: a2ui/surface.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/a2ui/user_action.py b/src/adcp/types/generated_poc/a2ui/user_action.py index a27eb02dc..0b087974b 100644 --- a/src/adcp/types/generated_poc/a2ui/user_action.py +++ b/src/adcp/types/generated_poc/a2ui/user_action.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: a2ui/user_action.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/account/get_account_financials_request.py b/src/adcp/types/generated_poc/account/get_account_financials_request.py index fd02b91a0..39e19426d 100644 --- a/src/adcp/types/generated_poc/account/get_account_financials_request.py +++ b/src/adcp/types/generated_poc/account/get_account_financials_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: account/get_account_financials_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/account/get_account_financials_response.py b/src/adcp/types/generated_poc/account/get_account_financials_response.py index 7b68de7f3..f7530ddd9 100644 --- a/src/adcp/types/generated_poc/account/get_account_financials_response.py +++ b/src/adcp/types/generated_poc/account/get_account_financials_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: account/get_account_financials_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/account/list_accounts_request.py b/src/adcp/types/generated_poc/account/list_accounts_request.py index 3588d9a77..7d450312c 100644 --- a/src/adcp/types/generated_poc/account/list_accounts_request.py +++ b/src/adcp/types/generated_poc/account/list_accounts_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: account/list_accounts_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/account/list_accounts_response.py b/src/adcp/types/generated_poc/account/list_accounts_response.py index aadde995d..c1eeb1fdd 100644 --- a/src/adcp/types/generated_poc/account/list_accounts_response.py +++ b/src/adcp/types/generated_poc/account/list_accounts_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: account/list_accounts_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/account/report_usage_request.py b/src/adcp/types/generated_poc/account/report_usage_request.py index d99369b47..99bdb1e94 100644 --- a/src/adcp/types/generated_poc/account/report_usage_request.py +++ b/src/adcp/types/generated_poc/account/report_usage_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: account/report_usage_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/account/report_usage_response.py b/src/adcp/types/generated_poc/account/report_usage_response.py index df82198f6..a36fd304a 100644 --- a/src/adcp/types/generated_poc/account/report_usage_response.py +++ b/src/adcp/types/generated_poc/account/report_usage_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: account/report_usage_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/account/sync_accounts_request.py b/src/adcp/types/generated_poc/account/sync_accounts_request.py index 1d2e9baac..e2cc4f80c 100644 --- a/src/adcp/types/generated_poc/account/sync_accounts_request.py +++ b/src/adcp/types/generated_poc/account/sync_accounts_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: account/sync_accounts_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/account/sync_accounts_response.py b/src/adcp/types/generated_poc/account/sync_accounts_response.py index 39f105ff9..18e532b09 100644 --- a/src/adcp/types/generated_poc/account/sync_accounts_response.py +++ b/src/adcp/types/generated_poc/account/sync_accounts_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: account/sync_accounts_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/account/sync_governance_request.py b/src/adcp/types/generated_poc/account/sync_governance_request.py index be02ff234..e30e5b351 100644 --- a/src/adcp/types/generated_poc/account/sync_governance_request.py +++ b/src/adcp/types/generated_poc/account/sync_governance_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: account/sync_governance_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/account/sync_governance_response.py b/src/adcp/types/generated_poc/account/sync_governance_response.py index 2e97031bf..0ea650d58 100644 --- a/src/adcp/types/generated_poc/account/sync_governance_response.py +++ b/src/adcp/types/generated_poc/account/sync_governance_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: account/sync_governance_response.json -# timestamp: 2026-04-18T20:45:21+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/adagents.py b/src/adcp/types/generated_poc/adagents.py index 5cd0d35bc..5a999e999 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -174,7 +174,7 @@ class AuthorizedAgents(AdCPBaseModel): authorization_type: Annotated[ Literal["property_ids"], Field(description="Discriminator indicating authorization by specific property IDs"), - ] + ] = "property_ids" property_ids: Annotated[ list[property_id.PropertyId], Field( @@ -261,7 +261,7 @@ class AuthorizedAgents1(AdCPBaseModel): authorization_type: Annotated[ Literal["property_tags"], Field(description="Discriminator indicating authorization by property tags"), - ] + ] = "property_tags" property_tags: Annotated[ list[property_tag.PropertyTag], Field( @@ -350,7 +350,7 @@ class AuthorizedAgents3(AdCPBaseModel): Field( description="Discriminator indicating authorization for properties from other publisher domains" ), - ] + ] = "publisher_properties" publisher_properties: Annotated[ list[publisher_property_selector.PublisherPropertySelector], Field( @@ -437,7 +437,7 @@ class AuthorizedAgents4(AdCPBaseModel): authorization_type: Annotated[ Literal["signal_ids"], Field(description="Discriminator indicating authorization by specific signal IDs"), - ] + ] = "signal_ids" signal_ids: Annotated[ list[SignalId], Field( @@ -477,7 +477,7 @@ class AuthorizedAgents5(AdCPBaseModel): authorization_type: Annotated[ Literal["signal_tags"], Field(description="Discriminator indicating authorization by signal tags"), - ] + ] = "signal_tags" signal_tags: Annotated[ list[SignalTag], Field( @@ -517,7 +517,7 @@ class AuthorizedAgents2(AdCPBaseModel): authorization_type: Annotated[ Literal["inline_properties"], Field(description="Discriminator indicating authorization by inline property definitions"), - ] + ] = "inline_properties" properties: Annotated[ list[property.Property], Field( diff --git a/src/adcp/types/generated_poc/brand/__init__.py b/src/adcp/types/generated_poc/brand/__init__.py index 9b480fea8..1e83c6ed8 100644 --- a/src/adcp/types/generated_poc/brand/__init__.py +++ b/src/adcp/types/generated_poc/brand/__init__.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/brand/acquire_rights_request.py b/src/adcp/types/generated_poc/brand/acquire_rights_request.py index 15bc24847..a04c4c707 100644 --- a/src/adcp/types/generated_poc/brand/acquire_rights_request.py +++ b/src/adcp/types/generated_poc/brand/acquire_rights_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand/acquire_rights_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/brand/acquire_rights_response.py b/src/adcp/types/generated_poc/brand/acquire_rights_response.py index edc1c86a7..10461df4f 100644 --- a/src/adcp/types/generated_poc/brand/acquire_rights_response.py +++ b/src/adcp/types/generated_poc/brand/acquire_rights_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand/acquire_rights_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -35,7 +35,7 @@ class AcquireRightsResponse2(AdCPBaseModel): status: Annotated[ Literal["pending_approval"], Field(description="Rights require approval from the rights holder"), - ] + ] = "pending_approval" brand_id: str detail: Annotated[str | None, Field(description="Explanation of what requires approval")] = None estimated_response_time: Annotated[ @@ -51,7 +51,9 @@ class AcquireRightsResponse3(AdCPBaseModel): extra="allow", ) rights_id: str - status: Annotated[Literal["rejected"], Field(description="Rights request was rejected")] + status: Annotated[Literal["rejected"], Field(description="Rights request was rejected")] = ( + "rejected" + ) brand_id: str reason: Annotated[ str, @@ -85,7 +87,7 @@ class AcquireRightsResponse1(AdCPBaseModel): rights_id: Annotated[str, Field(description="Rights grant identifier")] status: Annotated[ Literal["acquired"], Field(description="Rights have been cleared and credentials issued") - ] + ] = "acquired" brand_id: Annotated[str, Field(description="Brand identifier of the rights subject")] terms: Annotated[rights_terms.RightsTerms, Field(description="Agreed contractual terms")] generation_credentials: Annotated[ diff --git a/src/adcp/types/generated_poc/brand/creative_approval_request.py b/src/adcp/types/generated_poc/brand/creative_approval_request.py index f2ec3dd09..6da68c8b5 100644 --- a/src/adcp/types/generated_poc/brand/creative_approval_request.py +++ b/src/adcp/types/generated_poc/brand/creative_approval_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand/creative_approval_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/brand/creative_approval_response.py b/src/adcp/types/generated_poc/brand/creative_approval_response.py index 98b5f7fdd..7ab11f693 100644 --- a/src/adcp/types/generated_poc/brand/creative_approval_response.py +++ b/src/adcp/types/generated_poc/brand/creative_approval_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand/creative_approval_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -20,7 +20,7 @@ class CreativeApprovalResponse1(AdCPBaseModel): ) status: Annotated[ Literal["approved"], Field(description="Creative has been approved for distribution") - ] + ] = "approved" rights_id: str creative_id: Annotated[ str | None, Field(description="Echo of the buyer's creative identifier") @@ -39,7 +39,7 @@ class CreativeApprovalResponse2(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - status: Annotated[Literal["rejected"], Field(description="Creative was rejected")] + status: Annotated[Literal["rejected"], Field(description="Creative was rejected")] = "rejected" rights_id: str creative_id: Annotated[ str | None, Field(description="Echo of the buyer's creative identifier") @@ -60,7 +60,9 @@ class CreativeApprovalResponse3(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - status: Annotated[Literal["pending_review"], Field(description="Creative is queued for review")] + status: Annotated[ + Literal["pending_review"], Field(description="Creative is queued for review") + ] = "pending_review" rights_id: str creative_id: Annotated[ str | None, Field(description="Echo of the buyer's creative identifier") diff --git a/src/adcp/types/generated_poc/brand/get_brand_identity_request.py b/src/adcp/types/generated_poc/brand/get_brand_identity_request.py index 3965668bb..bcfda85f8 100644 --- a/src/adcp/types/generated_poc/brand/get_brand_identity_request.py +++ b/src/adcp/types/generated_poc/brand/get_brand_identity_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand/get_brand_identity_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/brand/get_brand_identity_response.py b/src/adcp/types/generated_poc/brand/get_brand_identity_response.py index 29e1f76cc..26719168a 100644 --- a/src/adcp/types/generated_poc/brand/get_brand_identity_response.py +++ b/src/adcp/types/generated_poc/brand/get_brand_identity_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand/get_brand_identity_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/brand/get_rights_request.py b/src/adcp/types/generated_poc/brand/get_rights_request.py index 2b5ceff6a..8599c02d7 100644 --- a/src/adcp/types/generated_poc/brand/get_rights_request.py +++ b/src/adcp/types/generated_poc/brand/get_rights_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand/get_rights_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/brand/get_rights_response.py b/src/adcp/types/generated_poc/brand/get_rights_response.py index fb361c664..83e5590fe 100644 --- a/src/adcp/types/generated_poc/brand/get_rights_response.py +++ b/src/adcp/types/generated_poc/brand/get_rights_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand/get_rights_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/brand/revocation_notification.py b/src/adcp/types/generated_poc/brand/revocation_notification.py index 011146291..41c9b3fcb 100644 --- a/src/adcp/types/generated_poc/brand/revocation_notification.py +++ b/src/adcp/types/generated_poc/brand/revocation_notification.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand/revocation_notification.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/brand/rights_pricing_option.py b/src/adcp/types/generated_poc/brand/rights_pricing_option.py index 33bbad433..7510929d9 100644 --- a/src/adcp/types/generated_poc/brand/rights_pricing_option.py +++ b/src/adcp/types/generated_poc/brand/rights_pricing_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand/rights_pricing_option.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/brand/rights_terms.py b/src/adcp/types/generated_poc/brand/rights_terms.py index 7876a88e3..8a4d1b4a1 100644 --- a/src/adcp/types/generated_poc/brand/rights_terms.py +++ b/src/adcp/types/generated_poc/brand/rights_terms.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand/rights_terms.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/brand/update_rights_request.py b/src/adcp/types/generated_poc/brand/update_rights_request.py index f046d38ef..3f36d9c52 100644 --- a/src/adcp/types/generated_poc/brand/update_rights_request.py +++ b/src/adcp/types/generated_poc/brand/update_rights_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand/update_rights_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/brand/update_rights_response.py b/src/adcp/types/generated_poc/brand/update_rights_response.py index c79f70b31..741b6620d 100644 --- a/src/adcp/types/generated_poc/brand/update_rights_response.py +++ b/src/adcp/types/generated_poc/brand/update_rights_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: brand/update_rights_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/content_standards/calibrate_content_request.py b/src/adcp/types/generated_poc/bundled/content_standards/calibrate_content_request.py index ec31cc23f..26b8733d6 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/calibrate_content_request.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/calibrate_content_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/calibrate_content_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -336,7 +336,7 @@ class Provenance(AdCPBaseModel): class Assets(AdCPBaseModel): - type: Literal["text"] + type: Literal["text"] = "text" role: Annotated[ Role | None, Field( @@ -920,7 +920,7 @@ class Identifiers(AdCPBaseModel): class AssetAccess4(AdCPBaseModel): - method: Literal["bearer_token"] + method: Literal["bearer_token"] = "bearer_token" token: Annotated[str, Field(description="OAuth2 bearer token for Authorization header")] @@ -930,7 +930,7 @@ class Provider(Enum): class AssetAccess5(AdCPBaseModel): - method: Literal["service_account"] + method: Literal["service_account"] = "service_account" provider: Annotated[Provider, Field(description="Cloud provider")] credentials: Annotated[ dict[str, Any] | None, Field(description="Service account credentials") @@ -938,7 +938,7 @@ class AssetAccess5(AdCPBaseModel): class AssetAccess6(AdCPBaseModel): - method: Literal["signed_url"] + method: Literal["signed_url"] = "signed_url" class AssetAccess(RootModel[AssetAccess4 | AssetAccess5 | AssetAccess6]): @@ -955,7 +955,7 @@ def __getattr__(self, name: str) -> Any: class Assets53(AdCPBaseModel): - type: Literal["image"] + type: Literal["image"] = "image" url: Annotated[AnyUrl, Field(description="Image URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -974,7 +974,7 @@ class Assets53(AdCPBaseModel): class Assets54(AdCPBaseModel): - type: Literal["video"] + type: Literal["video"] = "video" url: Annotated[AnyUrl, Field(description="Video URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -1007,7 +1007,7 @@ class Assets54(AdCPBaseModel): class Assets55(AdCPBaseModel): - type: Literal["audio"] + type: Literal["audio"] = "audio" url: Annotated[AnyUrl, Field(description="Audio URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None diff --git a/src/adcp/types/generated_poc/bundled/content_standards/calibrate_content_response.py b/src/adcp/types/generated_poc/bundled/content_standards/calibrate_content_response.py index 2871526b3..5bcfc8eba 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/calibrate_content_response.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/calibrate_content_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/calibrate_content_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/content_standards/create_content_standards_request.py b/src/adcp/types/generated_poc/bundled/content_standards/create_content_standards_request.py index 029d0448f..2c8d29bfd 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/create_content_standards_request.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/create_content_standards_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/create_content_standards_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -86,7 +86,7 @@ class GovernanceDomain(Enum): class Pass(AdCPBaseModel): - type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] + type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] = "url" value: Annotated[ AnyUrl, Field( @@ -423,7 +423,7 @@ class Provenance(AdCPBaseModel): class Assets(AdCPBaseModel): - type: Literal["text"] + type: Literal["text"] = "text" role: Annotated[ Role | None, Field( @@ -1007,7 +1007,7 @@ class Identifiers(AdCPBaseModel): class Fail(AdCPBaseModel): - type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] + type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] = "url" value: Annotated[ AnyUrl, Field( @@ -1144,7 +1144,7 @@ class Provenance53(AdCPBaseModel): class Assets60(AdCPBaseModel): - type: Literal["text"] + type: Literal["text"] = "text" role: Annotated[ Role | None, Field( @@ -1690,7 +1690,7 @@ class Exemplar(AdCPBaseModel): class AssetAccess7(AdCPBaseModel): - method: Literal["bearer_token"] + method: Literal["bearer_token"] = "bearer_token" token: Annotated[str, Field(description="OAuth2 bearer token for Authorization header")] @@ -1700,7 +1700,7 @@ class Provider(Enum): class AssetAccess8(AdCPBaseModel): - method: Literal["service_account"] + method: Literal["service_account"] = "service_account" provider: Annotated[Provider, Field(description="Cloud provider")] credentials: Annotated[ dict[str, Any] | None, Field(description="Service account credentials") @@ -1708,7 +1708,7 @@ class AssetAccess8(AdCPBaseModel): class AssetAccess9(AdCPBaseModel): - method: Literal["signed_url"] + method: Literal["signed_url"] = "signed_url" class AssetAccess(RootModel[AssetAccess7 | AssetAccess8 | AssetAccess9]): @@ -1868,7 +1868,7 @@ class Policy(AdCPBaseModel): class Assets57(AdCPBaseModel): - type: Literal["image"] + type: Literal["image"] = "image" url: Annotated[AnyUrl, Field(description="Image URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -1887,7 +1887,7 @@ class Assets57(AdCPBaseModel): class Assets58(AdCPBaseModel): - type: Literal["video"] + type: Literal["video"] = "video" url: Annotated[AnyUrl, Field(description="Video URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -1920,7 +1920,7 @@ class Assets58(AdCPBaseModel): class Assets59(AdCPBaseModel): - type: Literal["audio"] + type: Literal["audio"] = "audio" url: Annotated[AnyUrl, Field(description="Audio URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2016,7 +2016,7 @@ class Pass2(AdCPBaseModel): class Assets61(AdCPBaseModel): - type: Literal["image"] + type: Literal["image"] = "image" url: Annotated[AnyUrl, Field(description="Image URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2035,7 +2035,7 @@ class Assets61(AdCPBaseModel): class Assets62(AdCPBaseModel): - type: Literal["video"] + type: Literal["video"] = "video" url: Annotated[AnyUrl, Field(description="Video URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2068,7 +2068,7 @@ class Assets62(AdCPBaseModel): class Assets63(AdCPBaseModel): - type: Literal["audio"] + type: Literal["audio"] = "audio" url: Annotated[AnyUrl, Field(description="Audio URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None diff --git a/src/adcp/types/generated_poc/bundled/content_standards/create_content_standards_response.py b/src/adcp/types/generated_poc/bundled/content_standards/create_content_standards_response.py index d74097d10..ceadae0cd 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/create_content_standards_response.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/create_content_standards_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/create_content_standards_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/content_standards/get_content_standards_request.py b/src/adcp/types/generated_poc/bundled/content_standards/get_content_standards_request.py index b7d082c7c..c1f6731f2 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/get_content_standards_request.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/get_content_standards_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/get_content_standards_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/content_standards/get_content_standards_response.py b/src/adcp/types/generated_poc/bundled/content_standards/get_content_standards_response.py index 7c8099d34..ef5da01e2 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/get_content_standards_response.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/get_content_standards_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/get_content_standards_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -383,7 +383,7 @@ class Provenance(AdCPBaseModel): class Assets(AdCPBaseModel): - type: Literal["text"] + type: Literal["text"] = "text" role: Annotated[ Role | None, Field( @@ -1091,7 +1091,7 @@ class Provenance77(AdCPBaseModel): class Assets111(AdCPBaseModel): - type: Literal["text"] + type: Literal["text"] = "text" role: Annotated[ Role | None, Field( @@ -1629,7 +1629,7 @@ class PricingOption121(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["cpm"] + model: Literal["cpm"] = "cpm" cpm: Annotated[float, Field(description="Cost per thousand impressions", ge=0.0)] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] ext: Annotated[ @@ -1645,7 +1645,7 @@ class PricingOption122(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["percent_of_media"] + model: Literal["percent_of_media"] = "percent_of_media" percent: Annotated[ float, Field(description="Percentage of media spend, e.g. 15 = 15%", ge=0.0, le=100.0) ] @@ -1680,7 +1680,7 @@ class PricingOption123(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["flat_fee"] + model: Literal["flat_fee"] = "flat_fee" amount: Annotated[float, Field(description="Fixed charge for the billing period", ge=0.0)] period: Annotated[Period, Field(description="Billing period for the flat fee.")] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] @@ -1697,7 +1697,7 @@ class PricingOption124(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["per_unit"] + model: Literal["per_unit"] = "per_unit" unit: Annotated[ str, Field( @@ -1732,7 +1732,7 @@ class PricingOption125(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["custom"] + model: Literal["custom"] = "custom" description: Annotated[ str, Field( @@ -1892,7 +1892,7 @@ class Exemplar(AdCPBaseModel): class AssetAccess10(AdCPBaseModel): - method: Literal["bearer_token"] + method: Literal["bearer_token"] = "bearer_token" token: Annotated[str, Field(description="OAuth2 bearer token for Authorization header")] @@ -1902,7 +1902,7 @@ class Provider(Enum): class AssetAccess11(AdCPBaseModel): - method: Literal["service_account"] + method: Literal["service_account"] = "service_account" provider: Annotated[Provider, Field(description="Cloud provider")] credentials: Annotated[ dict[str, Any] | None, Field(description="Service account credentials") @@ -1910,7 +1910,7 @@ class AssetAccess11(AdCPBaseModel): class AssetAccess12(AdCPBaseModel): - method: Literal["signed_url"] + method: Literal["signed_url"] = "signed_url" class AssetAccess(RootModel[AssetAccess10 | AssetAccess11 | AssetAccess12]): @@ -2070,7 +2070,7 @@ class Policy(AdCPBaseModel): class Assets108(AdCPBaseModel): - type: Literal["image"] + type: Literal["image"] = "image" url: Annotated[AnyUrl, Field(description="Image URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2089,7 +2089,7 @@ class Assets108(AdCPBaseModel): class Assets109(AdCPBaseModel): - type: Literal["video"] + type: Literal["video"] = "video" url: Annotated[AnyUrl, Field(description="Video URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2122,7 +2122,7 @@ class Assets109(AdCPBaseModel): class Assets110(AdCPBaseModel): - type: Literal["audio"] + type: Literal["audio"] = "audio" url: Annotated[AnyUrl, Field(description="Audio URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2218,7 +2218,7 @@ class Pas(AdCPBaseModel): class Assets112(AdCPBaseModel): - type: Literal["image"] + type: Literal["image"] = "image" url: Annotated[AnyUrl, Field(description="Image URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2237,7 +2237,7 @@ class Assets112(AdCPBaseModel): class Assets113(AdCPBaseModel): - type: Literal["video"] + type: Literal["video"] = "video" url: Annotated[AnyUrl, Field(description="Video URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2270,7 +2270,7 @@ class Assets113(AdCPBaseModel): class Assets114(AdCPBaseModel): - type: Literal["audio"] + type: Literal["audio"] = "audio" url: Annotated[AnyUrl, Field(description="Audio URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None diff --git a/src/adcp/types/generated_poc/bundled/content_standards/get_media_buy_artifacts_request.py b/src/adcp/types/generated_poc/bundled/content_standards/get_media_buy_artifacts_request.py index dfd0f8276..334299557 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/get_media_buy_artifacts_request.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/get_media_buy_artifacts_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/get_media_buy_artifacts_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/content_standards/get_media_buy_artifacts_response.py b/src/adcp/types/generated_poc/bundled/content_standards/get_media_buy_artifacts_response.py index f309c1bbb..b71cc1d88 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/get_media_buy_artifacts_response.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/get_media_buy_artifacts_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/get_media_buy_artifacts_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -336,7 +336,7 @@ class Provenance(AdCPBaseModel): class Assets(AdCPBaseModel): - type: Literal["text"] + type: Literal["text"] = "text" role: Annotated[ Role | None, Field( @@ -1034,7 +1034,7 @@ class GetMediaBuyArtifactsResponse4(AdCPBaseModel): class AssetAccess13(AdCPBaseModel): - method: Literal["bearer_token"] + method: Literal["bearer_token"] = "bearer_token" token: Annotated[str, Field(description="OAuth2 bearer token for Authorization header")] @@ -1044,7 +1044,7 @@ class Provider(Enum): class AssetAccess14(AdCPBaseModel): - method: Literal["service_account"] + method: Literal["service_account"] = "service_account" provider: Annotated[Provider, Field(description="Cloud provider")] credentials: Annotated[ dict[str, Any] | None, Field(description="Service account credentials") @@ -1052,7 +1052,7 @@ class AssetAccess14(AdCPBaseModel): class AssetAccess15(AdCPBaseModel): - method: Literal["signed_url"] + method: Literal["signed_url"] = "signed_url" class AssetAccess(RootModel[AssetAccess13 | AssetAccess14 | AssetAccess15]): @@ -1069,7 +1069,7 @@ def __getattr__(self, name: str) -> Any: class Assets148(AdCPBaseModel): - type: Literal["image"] + type: Literal["image"] = "image" url: Annotated[AnyUrl, Field(description="Image URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -1088,7 +1088,7 @@ class Assets148(AdCPBaseModel): class Assets149(AdCPBaseModel): - type: Literal["video"] + type: Literal["video"] = "video" url: Annotated[AnyUrl, Field(description="Video URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -1121,7 +1121,7 @@ class Assets149(AdCPBaseModel): class Assets150(AdCPBaseModel): - type: Literal["audio"] + type: Literal["audio"] = "audio" url: Annotated[AnyUrl, Field(description="Audio URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None diff --git a/src/adcp/types/generated_poc/bundled/content_standards/list_content_standards_request.py b/src/adcp/types/generated_poc/bundled/content_standards/list_content_standards_request.py index d1da54a99..542ae3d29 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/list_content_standards_request.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/list_content_standards_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/list_content_standards_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/content_standards/list_content_standards_response.py b/src/adcp/types/generated_poc/bundled/content_standards/list_content_standards_response.py index 1905123d2..55a09922a 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/list_content_standards_response.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/list_content_standards_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/list_content_standards_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -383,7 +383,7 @@ class Provenance(AdCPBaseModel): class Assets(AdCPBaseModel): - type: Literal["text"] + type: Literal["text"] = "text" role: Annotated[ Role | None, Field( @@ -1091,7 +1091,7 @@ class Provenance120(AdCPBaseModel): class Assets155(AdCPBaseModel): - type: Literal["text"] + type: Literal["text"] = "text" role: Annotated[ Role | None, Field( @@ -1629,7 +1629,7 @@ class PricingOption151(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["cpm"] + model: Literal["cpm"] = "cpm" cpm: Annotated[float, Field(description="Cost per thousand impressions", ge=0.0)] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] ext: Annotated[ @@ -1645,7 +1645,7 @@ class PricingOption152(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["percent_of_media"] + model: Literal["percent_of_media"] = "percent_of_media" percent: Annotated[ float, Field(description="Percentage of media spend, e.g. 15 = 15%", ge=0.0, le=100.0) ] @@ -1680,7 +1680,7 @@ class PricingOption153(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["flat_fee"] + model: Literal["flat_fee"] = "flat_fee" amount: Annotated[float, Field(description="Fixed charge for the billing period", ge=0.0)] period: Annotated[Period, Field(description="Billing period for the flat fee.")] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] @@ -1697,7 +1697,7 @@ class PricingOption154(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["per_unit"] + model: Literal["per_unit"] = "per_unit" unit: Annotated[ str, Field( @@ -1732,7 +1732,7 @@ class PricingOption155(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["custom"] + model: Literal["custom"] = "custom" description: Annotated[ str, Field( @@ -1914,7 +1914,7 @@ class Exemplar(AdCPBaseModel): class AssetAccess16(AdCPBaseModel): - method: Literal["bearer_token"] + method: Literal["bearer_token"] = "bearer_token" token: Annotated[str, Field(description="OAuth2 bearer token for Authorization header")] @@ -1924,7 +1924,7 @@ class Provider(Enum): class AssetAccess17(AdCPBaseModel): - method: Literal["service_account"] + method: Literal["service_account"] = "service_account" provider: Annotated[Provider, Field(description="Cloud provider")] credentials: Annotated[ dict[str, Any] | None, Field(description="Service account credentials") @@ -1932,7 +1932,7 @@ class AssetAccess17(AdCPBaseModel): class AssetAccess18(AdCPBaseModel): - method: Literal["signed_url"] + method: Literal["signed_url"] = "signed_url" class AssetAccess(RootModel[AssetAccess16 | AssetAccess17 | AssetAccess18]): @@ -2092,7 +2092,7 @@ class Policy(AdCPBaseModel): class Assets152(AdCPBaseModel): - type: Literal["image"] + type: Literal["image"] = "image" url: Annotated[AnyUrl, Field(description="Image URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2111,7 +2111,7 @@ class Assets152(AdCPBaseModel): class Assets153(AdCPBaseModel): - type: Literal["video"] + type: Literal["video"] = "video" url: Annotated[AnyUrl, Field(description="Video URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2144,7 +2144,7 @@ class Assets153(AdCPBaseModel): class Assets154(AdCPBaseModel): - type: Literal["audio"] + type: Literal["audio"] = "audio" url: Annotated[AnyUrl, Field(description="Audio URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2240,7 +2240,7 @@ class Pas(AdCPBaseModel): class Assets156(AdCPBaseModel): - type: Literal["image"] + type: Literal["image"] = "image" url: Annotated[AnyUrl, Field(description="Image URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2259,7 +2259,7 @@ class Assets156(AdCPBaseModel): class Assets157(AdCPBaseModel): - type: Literal["video"] + type: Literal["video"] = "video" url: Annotated[AnyUrl, Field(description="Video URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2292,7 +2292,7 @@ class Assets157(AdCPBaseModel): class Assets158(AdCPBaseModel): - type: Literal["audio"] + type: Literal["audio"] = "audio" url: Annotated[AnyUrl, Field(description="Audio URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None diff --git a/src/adcp/types/generated_poc/bundled/content_standards/update_content_standards_request.py b/src/adcp/types/generated_poc/bundled/content_standards/update_content_standards_request.py index b0eaeb161..1fe24f02f 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/update_content_standards_request.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/update_content_standards_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/update_content_standards_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -86,7 +86,7 @@ class GovernanceDomain(Enum): class Pass(AdCPBaseModel): - type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] + type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] = "url" value: Annotated[ AnyUrl, Field( @@ -423,7 +423,7 @@ class Provenance(AdCPBaseModel): class Assets(AdCPBaseModel): - type: Literal["text"] + type: Literal["text"] = "text" role: Annotated[ Role | None, Field( @@ -1007,7 +1007,7 @@ class Identifiers(AdCPBaseModel): class Fail(AdCPBaseModel): - type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] + type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] = "url" value: Annotated[ AnyUrl, Field( @@ -1144,7 +1144,7 @@ class Provenance213(AdCPBaseModel): class Assets313(AdCPBaseModel): - type: Literal["text"] + type: Literal["text"] = "text" role: Annotated[ Role | None, Field( @@ -1690,7 +1690,7 @@ class Exemplar(AdCPBaseModel): class AssetAccess19(AdCPBaseModel): - method: Literal["bearer_token"] + method: Literal["bearer_token"] = "bearer_token" token: Annotated[str, Field(description="OAuth2 bearer token for Authorization header")] @@ -1700,7 +1700,7 @@ class Provider(Enum): class AssetAccess20(AdCPBaseModel): - method: Literal["service_account"] + method: Literal["service_account"] = "service_account" provider: Annotated[Provider, Field(description="Cloud provider")] credentials: Annotated[ dict[str, Any] | None, Field(description="Service account credentials") @@ -1708,7 +1708,7 @@ class AssetAccess20(AdCPBaseModel): class AssetAccess21(AdCPBaseModel): - method: Literal["signed_url"] + method: Literal["signed_url"] = "signed_url" class AssetAccess(RootModel[AssetAccess19 | AssetAccess20 | AssetAccess21]): @@ -1868,7 +1868,7 @@ class Policy(AdCPBaseModel): class Assets310(AdCPBaseModel): - type: Literal["image"] + type: Literal["image"] = "image" url: Annotated[AnyUrl, Field(description="Image URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -1887,7 +1887,7 @@ class Assets310(AdCPBaseModel): class Assets311(AdCPBaseModel): - type: Literal["video"] + type: Literal["video"] = "video" url: Annotated[AnyUrl, Field(description="Video URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -1920,7 +1920,7 @@ class Assets311(AdCPBaseModel): class Assets312(AdCPBaseModel): - type: Literal["audio"] + type: Literal["audio"] = "audio" url: Annotated[AnyUrl, Field(description="Audio URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2016,7 +2016,7 @@ class Pass5(AdCPBaseModel): class Assets314(AdCPBaseModel): - type: Literal["image"] + type: Literal["image"] = "image" url: Annotated[AnyUrl, Field(description="Image URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2035,7 +2035,7 @@ class Assets314(AdCPBaseModel): class Assets315(AdCPBaseModel): - type: Literal["video"] + type: Literal["video"] = "video" url: Annotated[AnyUrl, Field(description="Video URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -2068,7 +2068,7 @@ class Assets315(AdCPBaseModel): class Assets316(AdCPBaseModel): - type: Literal["audio"] + type: Literal["audio"] = "audio" url: Annotated[AnyUrl, Field(description="Audio URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None diff --git a/src/adcp/types/generated_poc/bundled/content_standards/update_content_standards_response.py b/src/adcp/types/generated_poc/bundled/content_standards/update_content_standards_response.py index ab72d90c3..a6ee570dc 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/update_content_standards_response.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/update_content_standards_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/update_content_standards_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/content_standards/validate_content_delivery_request.py b/src/adcp/types/generated_poc/bundled/content_standards/validate_content_delivery_request.py index 993b63083..6c4e6c8d8 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/validate_content_delivery_request.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/validate_content_delivery_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/validate_content_delivery_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -336,7 +336,7 @@ class Provenance(AdCPBaseModel): class Assets(AdCPBaseModel): - type: Literal["text"] + type: Literal["text"] = "text" role: Annotated[ Role | None, Field( @@ -925,7 +925,7 @@ class BrandContext(AdCPBaseModel): class AssetAccess22(AdCPBaseModel): - method: Literal["bearer_token"] + method: Literal["bearer_token"] = "bearer_token" token: Annotated[str, Field(description="OAuth2 bearer token for Authorization header")] @@ -935,7 +935,7 @@ class Provider(Enum): class AssetAccess23(AdCPBaseModel): - method: Literal["service_account"] + method: Literal["service_account"] = "service_account" provider: Annotated[Provider, Field(description="Cloud provider")] credentials: Annotated[ dict[str, Any] | None, Field(description="Service account credentials") @@ -943,7 +943,7 @@ class AssetAccess23(AdCPBaseModel): class AssetAccess24(AdCPBaseModel): - method: Literal["signed_url"] + method: Literal["signed_url"] = "signed_url" class AssetAccess(RootModel[AssetAccess22 | AssetAccess23 | AssetAccess24]): @@ -960,7 +960,7 @@ def __getattr__(self, name: str) -> Any: class Assets350(AdCPBaseModel): - type: Literal["image"] + type: Literal["image"] = "image" url: Annotated[AnyUrl, Field(description="Image URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -979,7 +979,7 @@ class Assets350(AdCPBaseModel): class Assets351(AdCPBaseModel): - type: Literal["video"] + type: Literal["video"] = "video" url: Annotated[AnyUrl, Field(description="Video URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -1012,7 +1012,7 @@ class Assets351(AdCPBaseModel): class Assets352(AdCPBaseModel): - type: Literal["audio"] + type: Literal["audio"] = "audio" url: Annotated[AnyUrl, Field(description="Audio URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None diff --git a/src/adcp/types/generated_poc/bundled/content_standards/validate_content_delivery_response.py b/src/adcp/types/generated_poc/bundled/content_standards/validate_content_delivery_response.py index 3d217760c..f4a44e50a 100644 --- a/src/adcp/types/generated_poc/bundled/content_standards/validate_content_delivery_response.py +++ b/src/adcp/types/generated_poc/bundled/content_standards/validate_content_delivery_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/content_standards/validate_content_delivery_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/core/tasks_get_request.py b/src/adcp/types/generated_poc/bundled/core/tasks_get_request.py index a96e4a9c1..9a82610a0 100644 --- a/src/adcp/types/generated_poc/bundled/core/tasks_get_request.py +++ b/src/adcp/types/generated_poc/bundled/core/tasks_get_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/core/tasks_get_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/core/tasks_get_response.py b/src/adcp/types/generated_poc/bundled/core/tasks_get_response.py index 0e0b3d189..7647a6a09 100644 --- a/src/adcp/types/generated_poc/bundled/core/tasks_get_response.py +++ b/src/adcp/types/generated_poc/bundled/core/tasks_get_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/core/tasks_get_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/core/tasks_list_request.py b/src/adcp/types/generated_poc/bundled/core/tasks_list_request.py index 0208914ca..348a9d5b1 100644 --- a/src/adcp/types/generated_poc/bundled/core/tasks_list_request.py +++ b/src/adcp/types/generated_poc/bundled/core/tasks_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/core/tasks_list_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/core/tasks_list_response.py b/src/adcp/types/generated_poc/bundled/core/tasks_list_response.py index b324e093d..dfb38eb64 100644 --- a/src/adcp/types/generated_poc/bundled/core/tasks_list_response.py +++ b/src/adcp/types/generated_poc/bundled/core/tasks_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/core/tasks_list_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/creative/get_creative_delivery_request.py b/src/adcp/types/generated_poc/bundled/creative/get_creative_delivery_request.py index 4771f2f1b..62b0a5d38 100644 --- a/src/adcp/types/generated_poc/bundled/creative/get_creative_delivery_request.py +++ b/src/adcp/types/generated_poc/bundled/creative/get_creative_delivery_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/creative/get_creative_delivery_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/creative/get_creative_delivery_response.py b/src/adcp/types/generated_poc/bundled/creative/get_creative_delivery_response.py index 79e9565cf..adaf155f5 100644 --- a/src/adcp/types/generated_poc/bundled/creative/get_creative_delivery_response.py +++ b/src/adcp/types/generated_poc/bundled/creative/get_creative_delivery_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/creative/get_creative_delivery_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -678,6 +678,12 @@ class Assets(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -883,6 +889,12 @@ class Assets116(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -1096,6 +1108,12 @@ class Assets117(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -1304,11 +1322,12 @@ class Assets118(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -1336,6 +1355,11 @@ class Assets118(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy85(DeclaredBy): @@ -1466,11 +1490,12 @@ class Assets119(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -1498,6 +1523,11 @@ class Assets119(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy86(DeclaredBy): @@ -1628,6 +1658,12 @@ class Assets120(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -1775,7 +1811,18 @@ class Assets121(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -1941,6 +1988,12 @@ class Assets122(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -2090,6 +2143,12 @@ class Assets123(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -2338,6 +2397,12 @@ class Assets124(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -2500,6 +2565,12 @@ class Assets125(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -2672,11 +2743,12 @@ class Assets126(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2700,6 +2772,11 @@ class Assets126(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy93(DeclaredBy): @@ -2830,11 +2907,12 @@ class Assets127(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2858,6 +2936,11 @@ class Assets127(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class MarkdownFlavor(Enum): @@ -2869,6 +2952,12 @@ class Assets128(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["markdown"], + Field( + description="Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + ), + ] = "markdown" content: Annotated[ str, Field( @@ -3051,6 +3140,12 @@ class Assets129(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class Type(Enum): @@ -3285,6 +3380,12 @@ class Assets130(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class RightsAgent(AdCPBaseModel): @@ -3576,7 +3677,7 @@ class Manifest(AdCPBaseModel): | Assets130, ], Field( - description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance — each asset must match at least one valid asset type schema." + description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches." ), ] rights: Annotated[ diff --git a/src/adcp/types/generated_poc/bundled/creative/get_creative_features_request.py b/src/adcp/types/generated_poc/bundled/creative/get_creative_features_request.py index 3d484dcd0..f0695f8a9 100644 --- a/src/adcp/types/generated_poc/bundled/creative/get_creative_features_request.py +++ b/src/adcp/types/generated_poc/bundled/creative/get_creative_features_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/creative/get_creative_features_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -330,6 +330,12 @@ class Assets(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -535,6 +541,12 @@ class Assets132(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -748,6 +760,12 @@ class Assets133(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -956,11 +974,12 @@ class Assets134(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -988,6 +1007,11 @@ class Assets134(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy99(DeclaredBy): @@ -1118,11 +1142,12 @@ class Assets135(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -1150,6 +1175,11 @@ class Assets135(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy100(DeclaredBy): @@ -1280,6 +1310,12 @@ class Assets136(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -1427,7 +1463,18 @@ class Assets137(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -1593,6 +1640,12 @@ class Assets138(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -1742,6 +1795,12 @@ class Assets139(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -1990,6 +2049,12 @@ class Assets140(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -2152,6 +2217,12 @@ class Assets141(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -2324,11 +2395,12 @@ class Assets142(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2352,6 +2424,11 @@ class Assets142(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy107(DeclaredBy): @@ -2482,11 +2559,12 @@ class Assets143(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2510,6 +2588,11 @@ class Assets143(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class MarkdownFlavor(Enum): @@ -2521,6 +2604,12 @@ class Assets144(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["markdown"], + Field( + description="Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + ), + ] = "markdown" content: Annotated[ str, Field( @@ -2703,6 +2792,12 @@ class Assets145(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class Type(Enum): @@ -2968,6 +3063,12 @@ class Assets146(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class RightsAgent(AdCPBaseModel): @@ -3259,7 +3360,7 @@ class CreativeManifest(AdCPBaseModel): | Assets146, ], Field( - description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance — each asset must match at least one valid asset type schema." + description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches." ), ] rights: Annotated[ diff --git a/src/adcp/types/generated_poc/bundled/creative/get_creative_features_response.py b/src/adcp/types/generated_poc/bundled/creative/get_creative_features_response.py index 6104b81c6..bec0c0f36 100644 --- a/src/adcp/types/generated_poc/bundled/creative/get_creative_features_response.py +++ b/src/adcp/types/generated_poc/bundled/creative/get_creative_features_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/creative/get_creative_features_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/creative/list_creative_formats_request.py b/src/adcp/types/generated_poc/bundled/creative/list_creative_formats_request.py index 730285a46..649e1ca52 100644 --- a/src/adcp/types/generated_poc/bundled/creative/list_creative_formats_request.py +++ b/src/adcp/types/generated_poc/bundled/creative/list_creative_formats_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/creative/list_creative_formats_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/creative/list_creative_formats_response.py b/src/adcp/types/generated_poc/bundled/creative/list_creative_formats_response.py index bae6152b7..95617491a 100644 --- a/src/adcp/types/generated_poc/bundled/creative/list_creative_formats_response.py +++ b/src/adcp/types/generated_poc/bundled/creative/list_creative_formats_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/creative/list_creative_formats_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -1260,7 +1260,7 @@ class PricingOption171(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["cpm"] + model: Literal["cpm"] = "cpm" cpm: Annotated[float, Field(description="Cost per thousand impressions", ge=0.0)] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] ext: Annotated[ @@ -1276,7 +1276,7 @@ class PricingOption172(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["percent_of_media"] + model: Literal["percent_of_media"] = "percent_of_media" percent: Annotated[ float, Field(description="Percentage of media spend, e.g. 15 = 15%", ge=0.0, le=100.0) ] @@ -1311,7 +1311,7 @@ class PricingOption173(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["flat_fee"] + model: Literal["flat_fee"] = "flat_fee" amount: Annotated[float, Field(description="Fixed charge for the billing period", ge=0.0)] period: Annotated[Period, Field(description="Billing period for the flat fee.")] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] @@ -1328,7 +1328,7 @@ class PricingOption174(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["per_unit"] + model: Literal["per_unit"] = "per_unit" unit: Annotated[ str, Field( @@ -1363,7 +1363,7 @@ class PricingOption175(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["custom"] + model: Literal["custom"] = "custom" description: Annotated[ str, Field( @@ -1542,7 +1542,7 @@ class ScalarBinding(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["scalar"] + kind: Literal["scalar"] = "scalar" asset_id: Annotated[ str, Field( @@ -1568,7 +1568,7 @@ class AssetPoolBinding(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["asset_pool"] + kind: Literal["asset_pool"] = "asset_pool" asset_id: Annotated[ str, Field( @@ -1725,7 +1725,7 @@ class BaseIndividualAsset(AdCPBaseModel): item_type: Annotated[ Literal["individual"], Field(description="Discriminator indicating this is an individual asset"), - ] + ] = "individual" asset_id: Annotated[ str, Field( @@ -1901,7 +1901,7 @@ class FieldBindings(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["catalog_group"] + kind: Literal["catalog_group"] = "catalog_group" format_group_id: Annotated[ str, Field(description="The asset_group_id of a repeatable_group in the format's assets array."), @@ -2130,7 +2130,7 @@ class Assets200(AdCPBaseModel): item_type: Annotated[ Literal["repeatable_group"], Field(description="Discriminator indicating this is a repeatable asset group"), - ] + ] = "repeatable_group" asset_group_id: Annotated[ str, Field(description="Identifier for this asset group (e.g., 'product', 'slide', 'card')") ] diff --git a/src/adcp/types/generated_poc/bundled/creative/list_creatives_request.py b/src/adcp/types/generated_poc/bundled/creative/list_creatives_request.py index 08bd8a3d4..e5944d46f 100644 --- a/src/adcp/types/generated_poc/bundled/creative/list_creatives_request.py +++ b/src/adcp/types/generated_poc/bundled/creative/list_creatives_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/creative/list_creatives_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/creative/list_creatives_response.py b/src/adcp/types/generated_poc/bundled/creative/list_creatives_response.py index 1a0eca883..784036b6f 100644 --- a/src/adcp/types/generated_poc/bundled/creative/list_creatives_response.py +++ b/src/adcp/types/generated_poc/bundled/creative/list_creatives_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/creative/list_creatives_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -598,7 +598,7 @@ class FormatId(AdCPBaseModel): ] = None -class Status22(Enum): +class Status26(Enum): processing = "processing" pending_review = "pending_review" approved = "approved" @@ -877,6 +877,12 @@ class Assets(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -1082,6 +1088,12 @@ class Assets214(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -1295,6 +1307,12 @@ class Assets215(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -1503,11 +1521,12 @@ class Assets216(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -1535,6 +1554,11 @@ class Assets216(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy128(DeclaredBy): @@ -1665,11 +1689,12 @@ class Assets217(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -1697,6 +1722,11 @@ class Assets217(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy129(DeclaredBy): @@ -1827,6 +1857,12 @@ class Assets218(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -1974,7 +2010,18 @@ class Assets219(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -2140,6 +2187,12 @@ class Assets220(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -2289,6 +2342,12 @@ class Assets221(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -2537,6 +2596,12 @@ class Assets222(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -2699,6 +2764,12 @@ class Assets223(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -2871,11 +2942,12 @@ class Assets224(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2899,6 +2971,11 @@ class Assets224(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy136(DeclaredBy): @@ -3029,11 +3106,12 @@ class Assets225(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -3057,6 +3135,11 @@ class Assets225(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class MarkdownFlavor(Enum): @@ -3068,6 +3151,12 @@ class Assets226(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["markdown"], + Field( + description="Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + ), + ] = "markdown" content: Annotated[ str, Field( @@ -3250,6 +3339,12 @@ class Assets227(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class Type(Enum): @@ -3515,6 +3610,12 @@ class Assets228(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class VariableType(Enum): @@ -3616,7 +3717,7 @@ class Items(AdCPBaseModel): asset_kind: Annotated[ Literal["media"], Field(description="Discriminator indicating this is a media asset with content_uri"), - ] + ] = "media" asset_type: Annotated[ str, Field( @@ -3636,7 +3737,7 @@ class Items1(AdCPBaseModel): asset_kind: Annotated[ Literal["text"], Field(description="Discriminator indicating this is a text asset with content"), - ] + ] = "text" asset_type: Annotated[ str, Field( @@ -3658,7 +3759,7 @@ class PricingOption181(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["cpm"] + model: Literal["cpm"] = "cpm" cpm: Annotated[float, Field(description="Cost per thousand impressions", ge=0.0)] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] ext: Annotated[ @@ -3674,7 +3775,7 @@ class PricingOption182(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["percent_of_media"] + model: Literal["percent_of_media"] = "percent_of_media" percent: Annotated[ float, Field(description="Percentage of media spend, e.g. 15 = 15%", ge=0.0, le=100.0) ] @@ -3709,7 +3810,7 @@ class PricingOption183(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["flat_fee"] + model: Literal["flat_fee"] = "flat_fee" amount: Annotated[float, Field(description="Fixed charge for the billing period", ge=0.0)] period: Annotated[Period, Field(description="Billing period for the flat fee.")] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] @@ -3726,7 +3827,7 @@ class PricingOption184(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["per_unit"] + model: Literal["per_unit"] = "per_unit" unit: Annotated[ str, Field( @@ -3761,7 +3862,7 @@ class PricingOption185(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["custom"] + model: Literal["custom"] = "custom" description: Annotated[ str, Field( @@ -3975,7 +4076,7 @@ class Creative(AdCPBaseModel): ), ] status: Annotated[ - Status22, + Status26, Field(description="Current approval status of the creative", title="Creative Status"), ] created_date: Annotated[AwareDatetime, Field(description="When the creative was created")] @@ -4001,7 +4102,9 @@ class Creative(AdCPBaseModel): | Assets228, ] | None, - Field(description="Assets for this creative, keyed by asset_id"), + Field( + description="Assets for this creative, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema." + ), ] = None tags: Annotated[ list[str] | None, Field(description="User-defined tags for organization and searchability") diff --git a/src/adcp/types/generated_poc/bundled/creative/preview_creative_request.py b/src/adcp/types/generated_poc/bundled/creative/preview_creative_request.py index ac810aa21..499e29b1f 100644 --- a/src/adcp/types/generated_poc/bundled/creative/preview_creative_request.py +++ b/src/adcp/types/generated_poc/bundled/creative/preview_creative_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/creative/preview_creative_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -328,6 +328,12 @@ class Assets(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -533,6 +539,12 @@ class Assets246(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -746,6 +758,12 @@ class Assets247(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -954,11 +972,12 @@ class Assets248(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -986,6 +1005,11 @@ class Assets248(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy155(DeclaredBy): @@ -1116,11 +1140,12 @@ class Assets249(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -1148,6 +1173,11 @@ class Assets249(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy156(DeclaredBy): @@ -1278,6 +1308,12 @@ class Assets250(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -1425,7 +1461,18 @@ class Assets251(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -1591,6 +1638,12 @@ class Assets252(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -1740,6 +1793,12 @@ class Assets253(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -1988,6 +2047,12 @@ class Assets254(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -2150,6 +2215,12 @@ class Assets255(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -2322,11 +2393,12 @@ class Assets256(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2350,6 +2422,11 @@ class Assets256(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy163(DeclaredBy): @@ -2480,11 +2557,12 @@ class Assets257(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2508,6 +2586,11 @@ class Assets257(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class MarkdownFlavor(Enum): @@ -2519,6 +2602,12 @@ class Assets258(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["markdown"], + Field( + description="Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + ), + ] = "markdown" content: Annotated[ str, Field( @@ -2701,6 +2790,12 @@ class Assets259(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class Type(Enum): @@ -2966,6 +3061,12 @@ class Assets260(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class RightsAgent(AdCPBaseModel): @@ -3257,7 +3358,7 @@ class CreativeManifest(AdCPBaseModel): | Assets260, ], Field( - description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance — each asset must match at least one valid asset type schema." + description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches." ), ] rights: Annotated[ @@ -3450,6 +3551,12 @@ class Assets261(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -3594,6 +3701,12 @@ class Assets262(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -3807,6 +3920,12 @@ class Assets263(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -3972,11 +4091,12 @@ class Assets264(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -4004,6 +4124,11 @@ class Assets264(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy169(DeclaredBy): @@ -4134,11 +4259,12 @@ class Assets265(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -4166,6 +4292,11 @@ class Assets265(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy170(DeclaredBy): @@ -4296,6 +4427,12 @@ class Assets266(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -4437,7 +4574,18 @@ class Assets267(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -4585,6 +4733,12 @@ class Assets268(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -4728,6 +4882,12 @@ class Assets269(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -4878,6 +5038,12 @@ class Assets270(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -5040,6 +5206,12 @@ class Assets271(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -5181,11 +5353,12 @@ class Assets272(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -5209,6 +5382,11 @@ class Assets272(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy177(DeclaredBy): @@ -5339,11 +5517,12 @@ class Assets273(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -5367,6 +5546,11 @@ class Assets273(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class Assets274(Assets258): @@ -5484,6 +5668,12 @@ class Assets275(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class FeedFieldMapping13(FeedFieldMapping): @@ -5591,6 +5781,12 @@ class Assets276(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class Right7(Right): @@ -5757,7 +5953,7 @@ class CreativeManifest6(AdCPBaseModel): | Assets276, ], Field( - description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance — each asset must match at least one valid asset type schema." + description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches." ), ] rights: Annotated[ diff --git a/src/adcp/types/generated_poc/bundled/creative/preview_creative_response.py b/src/adcp/types/generated_poc/bundled/creative/preview_creative_response.py index 4a270d775..c4113349d 100644 --- a/src/adcp/types/generated_poc/bundled/creative/preview_creative_response.py +++ b/src/adcp/types/generated_poc/bundled/creative/preview_creative_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/creative/preview_creative_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -43,7 +43,7 @@ class Renders(AdCPBaseModel): ] output_format: Annotated[ Literal["url"], Field(description="Discriminator indicating preview_url is provided") - ] + ] = "url" preview_url: Annotated[ AnyUrl, Field( @@ -74,7 +74,7 @@ class Renders13(AdCPBaseModel): ] output_format: Annotated[ Literal["html"], Field(description="Discriminator indicating preview_html is provided") - ] + ] = "html" preview_html: Annotated[ str, Field( @@ -107,7 +107,7 @@ class Renders14(AdCPBaseModel): Field( description="Discriminator indicating both preview_url and preview_html are provided" ), - ] + ] = "both" preview_url: Annotated[ AnyUrl, Field( @@ -169,7 +169,7 @@ class PreviewCreativeResponse4(AdCPBaseModel): response_type: Annotated[ Literal["single"], Field(description="Discriminator indicating this is a single preview response"), - ] + ] = "single" previews: Annotated[ list[Preview], Field( @@ -344,7 +344,7 @@ class PreviewCreativeResponse5(AdCPBaseModel): response_type: Annotated[ Literal["batch"], Field(description="Discriminator indicating this is a batch preview response"), - ] + ] = "batch" results: Annotated[ list[Results | Results3], Field( @@ -699,6 +699,12 @@ class Assets(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -904,6 +910,12 @@ class Assets278(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -1117,6 +1129,12 @@ class Assets279(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -1325,11 +1343,12 @@ class Assets280(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -1357,6 +1376,11 @@ class Assets280(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy183(DeclaredBy): @@ -1487,11 +1511,12 @@ class Assets281(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -1519,6 +1544,11 @@ class Assets281(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy184(DeclaredBy): @@ -1649,6 +1679,12 @@ class Assets282(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -1796,7 +1832,18 @@ class Assets283(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -1962,6 +2009,12 @@ class Assets284(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -2111,6 +2164,12 @@ class Assets285(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -2359,6 +2418,12 @@ class Assets286(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -2521,6 +2586,12 @@ class Assets287(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -2693,11 +2764,12 @@ class Assets288(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2721,6 +2793,11 @@ class Assets288(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy191(DeclaredBy): @@ -2851,11 +2928,12 @@ class Assets289(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2879,6 +2957,11 @@ class Assets289(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class MarkdownFlavor(Enum): @@ -2890,6 +2973,12 @@ class Assets290(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["markdown"], + Field( + description="Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + ), + ] = "markdown" content: Annotated[ str, Field( @@ -3072,6 +3161,12 @@ class Assets291(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class Type(Enum): @@ -3337,6 +3432,12 @@ class Assets292(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class RightsAgent(AdCPBaseModel): @@ -3628,7 +3729,7 @@ class Manifest(AdCPBaseModel): | Assets292, ], Field( - description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance — each asset must match at least one valid asset type schema." + description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches." ), ] rights: Annotated[ @@ -3666,7 +3767,7 @@ class PreviewCreativeResponse6(AdCPBaseModel): response_type: Annotated[ Literal["variant"], Field(description="Discriminator indicating this is a variant preview response"), - ] + ] = "variant" variant_id: Annotated[str, Field(description="Platform-assigned variant identifier")] creative_id: Annotated[ str | None, Field(description="Creative identifier this variant belongs to") diff --git a/src/adcp/types/generated_poc/bundled/creative/sync_creatives_request.py b/src/adcp/types/generated_poc/bundled/creative/sync_creatives_request.py index 43a8d8a54..04ecbd376 100644 --- a/src/adcp/types/generated_poc/bundled/creative/sync_creatives_request.py +++ b/src/adcp/types/generated_poc/bundled/creative/sync_creatives_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/creative/sync_creatives_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -425,6 +425,12 @@ class Assets(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -630,6 +636,12 @@ class Assets294(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -843,6 +855,12 @@ class Assets295(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -1051,11 +1069,12 @@ class Assets296(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -1083,6 +1102,11 @@ class Assets296(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy198(DeclaredBy): @@ -1213,11 +1237,12 @@ class Assets297(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -1245,6 +1270,11 @@ class Assets297(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy199(DeclaredBy): @@ -1375,6 +1405,12 @@ class Assets298(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -1522,7 +1558,18 @@ class Assets299(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -1688,6 +1735,12 @@ class Assets300(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -1837,6 +1890,12 @@ class Assets301(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -2085,6 +2144,12 @@ class Assets302(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -2247,6 +2312,12 @@ class Assets303(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -2419,11 +2490,12 @@ class Assets304(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2447,6 +2519,11 @@ class Assets304(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy206(DeclaredBy): @@ -2577,11 +2654,12 @@ class Assets305(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2605,6 +2683,11 @@ class Assets305(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class MarkdownFlavor(Enum): @@ -2616,6 +2699,12 @@ class Assets306(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["markdown"], + Field( + description="Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + ), + ] = "markdown" content: Annotated[ str, Field( @@ -2798,6 +2887,12 @@ class Assets307(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class Type(Enum): @@ -3063,6 +3158,12 @@ class Assets308(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class Input(AdCPBaseModel): @@ -3268,7 +3369,9 @@ class Creative(AdCPBaseModel): | Assets307 | Assets308, ], - Field(description="Assets required by the format, keyed by asset_id"), + Field( + description="Assets required by the format, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema." + ), ] inputs: Annotated[ list[Input] | None, diff --git a/src/adcp/types/generated_poc/bundled/creative/sync_creatives_response.py b/src/adcp/types/generated_poc/bundled/creative/sync_creatives_response.py index 16107a95f..af79e0dc3 100644 --- a/src/adcp/types/generated_poc/bundled/creative/sync_creatives_response.py +++ b/src/adcp/types/generated_poc/bundled/creative/sync_creatives_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/creative/sync_creatives_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -512,7 +512,7 @@ class Action(Enum): deleted = "deleted" -class Status34(Enum): +class Status38(Enum): processing = "processing" pending_review = "pending_review" approved = "approved" @@ -689,7 +689,7 @@ class Creative(AdCPBaseModel): ), ] status: Annotated[ - Status34 | None, + Status38 | None, Field( description="Advisory review-lifecycle state of the creative after this sync — a UI hint and polling-scheduling signal, NOT a spend-authorization gate. Orthogonal to action — action says what the sync did (created, updated, ...); status says where the creative sits in review. Values come from CreativeStatus only (processing, pending_review, approved, rejected, archived) — never from CreativeAction. Sellers with async review return processing or pending_review; sellers with synchronous review MAY return a terminal value (approved, rejected). Buyers MUST NOT gate downstream spend or package activation on status: approved from this response — a compromised or buggy seller could declare approved while bypassing content-policy review. Reconcile via list_creatives or a signed review webhook before committing spend. Authoritative state is always via list_creatives. MUST be omitted when action is failed or deleted (the creative has no meaningful review state — failure details belong in the errors array; deleted creatives are gone from the library). Omit entirely when the seller has no review lifecycle at all.", title="Creative Status", @@ -812,7 +812,7 @@ class SyncCreativesResponse6(AdCPBaseModel): Field( description="Task-level status literal. Discriminates this async envelope from the synchronous success shape, whose creatives array carries per-item approval state via CreativeStatus. See task-status.json for the full task-status enum." ), - ] + ] = "submitted" task_id: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/bundled/media_buy/build_creative_request.py b/src/adcp/types/generated_poc/bundled/media_buy/build_creative_request.py index 7c5efccff..5d7358931 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/build_creative_request.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/build_creative_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/build_creative_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -330,6 +330,12 @@ class Assets(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -535,6 +541,12 @@ class Assets5(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -748,6 +760,12 @@ class Assets6(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -956,11 +974,12 @@ class Assets7(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -988,6 +1007,11 @@ class Assets7(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy4(DeclaredBy): @@ -1118,11 +1142,12 @@ class Assets8(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -1150,6 +1175,11 @@ class Assets8(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy5(DeclaredBy): @@ -1280,6 +1310,12 @@ class Assets9(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -1427,7 +1463,18 @@ class Assets10(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -1593,6 +1640,12 @@ class Assets11(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -1742,6 +1795,12 @@ class Assets12(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -1990,6 +2049,12 @@ class Assets13(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -2152,6 +2217,12 @@ class Assets14(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -2324,11 +2395,12 @@ class Assets15(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2352,6 +2424,11 @@ class Assets15(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy12(DeclaredBy): @@ -2482,11 +2559,12 @@ class Assets16(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2510,6 +2588,11 @@ class Assets16(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class MarkdownFlavor(Enum): @@ -2521,6 +2604,12 @@ class Assets17(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["markdown"], + Field( + description="Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + ), + ] = "markdown" content: Annotated[ str, Field( @@ -2703,6 +2792,12 @@ class Assets18(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class Type(Enum): @@ -2968,6 +3063,12 @@ class Assets19(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class RightsAgent(AdCPBaseModel): @@ -3259,7 +3360,7 @@ class CreativeManifest(AdCPBaseModel): | Assets19, ], Field( - description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance — each asset must match at least one valid asset type schema." + description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches." ), ] rights: Annotated[ diff --git a/src/adcp/types/generated_poc/bundled/media_buy/build_creative_response.py b/src/adcp/types/generated_poc/bundled/media_buy/build_creative_response.py index 5c14c0a9a..2c2a7acad 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/build_creative_response.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/build_creative_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/build_creative_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -322,6 +322,12 @@ class Assets(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -527,6 +533,12 @@ class Assets21(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -740,6 +752,12 @@ class Assets22(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -948,11 +966,12 @@ class Assets23(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -980,6 +999,11 @@ class Assets23(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy18(DeclaredBy): @@ -1110,11 +1134,12 @@ class Assets24(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -1142,6 +1167,11 @@ class Assets24(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy19(DeclaredBy): @@ -1272,6 +1302,12 @@ class Assets25(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -1419,7 +1455,18 @@ class Assets26(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -1585,6 +1632,12 @@ class Assets27(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -1734,6 +1787,12 @@ class Assets28(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -1982,6 +2041,12 @@ class Assets29(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -2144,6 +2209,12 @@ class Assets30(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -2316,11 +2387,12 @@ class Assets31(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2344,6 +2416,11 @@ class Assets31(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy26(DeclaredBy): @@ -2474,11 +2551,12 @@ class Assets32(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -2502,6 +2580,11 @@ class Assets32(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class MarkdownFlavor(Enum): @@ -2513,6 +2596,12 @@ class Assets33(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["markdown"], + Field( + description="Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + ), + ] = "markdown" content: Annotated[ str, Field( @@ -2695,6 +2784,12 @@ class Assets34(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class Type(Enum): @@ -2960,6 +3055,12 @@ class Assets35(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class RightsAgent(AdCPBaseModel): @@ -3251,7 +3352,7 @@ class CreativeManifest(AdCPBaseModel): | Assets35, ], Field( - description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance — each asset must match at least one valid asset type schema." + description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches." ), ] rights: Annotated[ @@ -3314,7 +3415,7 @@ class Renders(AdCPBaseModel): ] output_format: Annotated[ Literal["url"], Field(description="Discriminator indicating preview_url is provided") - ] + ] = "url" preview_url: Annotated[ AnyUrl, Field( @@ -3345,7 +3446,7 @@ class Renders1(AdCPBaseModel): ] output_format: Annotated[ Literal["html"], Field(description="Discriminator indicating preview_html is provided") - ] + ] = "html" preview_html: Annotated[ str, Field( @@ -3378,7 +3479,7 @@ class Renders2(AdCPBaseModel): Field( description="Discriminator indicating both preview_url and preview_html are provided" ), - ] + ] = "both" preview_url: Annotated[ AnyUrl, Field( @@ -3725,6 +3826,12 @@ class Assets36(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -3869,6 +3976,12 @@ class Assets37(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -4082,6 +4195,12 @@ class Assets38(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -4247,11 +4366,12 @@ class Assets39(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -4279,6 +4399,11 @@ class Assets39(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy32(DeclaredBy): @@ -4409,11 +4534,12 @@ class Assets40(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -4441,6 +4567,11 @@ class Assets40(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy33(DeclaredBy): @@ -4571,6 +4702,12 @@ class Assets41(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -4712,7 +4849,18 @@ class Assets42(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -4860,6 +5008,12 @@ class Assets43(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -5003,6 +5157,12 @@ class Assets44(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -5153,6 +5313,12 @@ class Assets45(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -5315,6 +5481,12 @@ class Assets46(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -5456,11 +5628,12 @@ class Assets47(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -5484,6 +5657,11 @@ class Assets47(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy40(DeclaredBy): @@ -5614,11 +5792,12 @@ class Assets48(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -5642,6 +5821,11 @@ class Assets48(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class Assets49(Assets33): @@ -5759,6 +5943,12 @@ class Assets50(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class FeedFieldMapping2(FeedFieldMapping): @@ -5866,6 +6056,12 @@ class Assets51(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class Right2(Right): @@ -6032,7 +6228,7 @@ class CreativeManifest3(AdCPBaseModel): | Assets51, ], Field( - description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance — each asset must match at least one valid asset type schema." + description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches." ), ] rights: Annotated[ diff --git a/src/adcp/types/generated_poc/bundled/media_buy/create_media_buy_request.py b/src/adcp/types/generated_poc/bundled/media_buy/create_media_buy_request.py index deaecfe9f..c39e482f4 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/create_media_buy_request.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/create_media_buy_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/create_media_buy_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -534,7 +534,7 @@ class Target(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["cost_per"] + kind: Literal["cost_per"] = "cost_per" value: Annotated[ float, Field(description="Target cost per metric unit in the buy currency", gt=0.0) ] @@ -544,7 +544,7 @@ class Target1(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["threshold_rate"] + kind: Literal["threshold_rate"] = "threshold_rate" value: Annotated[ float, Field( @@ -558,7 +558,7 @@ class OptimizationGoals(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["metric"] + kind: Literal["metric"] = "metric" metric: Annotated[ Metric, Field( @@ -641,7 +641,7 @@ class Target2(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["cost_per"] + kind: Literal["cost_per"] = "cost_per" value: Annotated[float, Field(description="Target cost per event in the buy currency", gt=0.0)] @@ -649,7 +649,7 @@ class Target3(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["per_ad_spend"] + kind: Literal["per_ad_spend"] = "per_ad_spend" value: Annotated[ float, Field(description="Target return ratio (e.g., 4.0 means $4 of value per $1 spent)", gt=0.0), @@ -660,7 +660,7 @@ class Target4(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["maximize_value"] + kind: Literal["maximize_value"] = "maximize_value" class PostClick(Window): @@ -693,7 +693,7 @@ class OptimizationGoals1(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["event"] + kind: Literal["event"] = "event" event_sources: Annotated[ list[EventSource], Field( @@ -2126,6 +2126,12 @@ class Assets(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -2331,6 +2337,12 @@ class Assets65(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -2544,6 +2556,12 @@ class Assets66(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -2752,11 +2770,12 @@ class Assets67(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -2784,6 +2803,11 @@ class Assets67(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy61(DeclaredBy): @@ -2914,11 +2938,12 @@ class Assets68(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -2946,6 +2971,11 @@ class Assets68(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy62(DeclaredBy): @@ -3076,6 +3106,12 @@ class Assets69(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -3223,7 +3259,18 @@ class Assets70(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -3389,6 +3436,12 @@ class Assets71(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -3538,6 +3591,12 @@ class Assets72(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -3786,6 +3845,12 @@ class Assets73(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -3948,6 +4013,12 @@ class Assets74(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -4120,11 +4191,12 @@ class Assets75(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -4148,6 +4220,11 @@ class Assets75(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy69(DeclaredBy): @@ -4278,11 +4355,12 @@ class Assets76(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -4306,6 +4384,11 @@ class Assets76(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class MarkdownFlavor(Enum): @@ -4317,6 +4400,12 @@ class Assets77(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["markdown"], + Field( + description="Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + ), + ] = "markdown" content: Annotated[ str, Field( @@ -4499,6 +4588,12 @@ class Assets78(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class FeedFieldMapping4(FeedFieldMapping): @@ -4606,6 +4701,12 @@ class Assets79(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class Input(AdCPBaseModel): @@ -4811,7 +4912,9 @@ class Creative(AdCPBaseModel): | Assets78 | Assets79, ], - Field(description="Assets required by the format, keyed by asset_id"), + Field( + description="Assets required by the format, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema." + ), ] inputs: Annotated[ list[Input] | None, diff --git a/src/adcp/types/generated_poc/bundled/media_buy/create_media_buy_response.py b/src/adcp/types/generated_poc/bundled/media_buy/create_media_buy_response.py index eee6156d3..0eb425da7 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/create_media_buy_response.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/create_media_buy_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/create_media_buy_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -2273,7 +2273,7 @@ class Target(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["cost_per"] + kind: Literal["cost_per"] = "cost_per" value: Annotated[ float, Field(description="Target cost per metric unit in the buy currency", gt=0.0) ] @@ -2283,7 +2283,7 @@ class Target6(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["threshold_rate"] + kind: Literal["threshold_rate"] = "threshold_rate" value: Annotated[ float, Field( @@ -2297,7 +2297,7 @@ class OptimizationGoals(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["metric"] + kind: Literal["metric"] = "metric" metric: Annotated[ Metric3, Field( @@ -2380,7 +2380,7 @@ class Target7(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["cost_per"] + kind: Literal["cost_per"] = "cost_per" value: Annotated[float, Field(description="Target cost per event in the buy currency", gt=0.0)] @@ -2388,7 +2388,7 @@ class Target8(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["per_ad_spend"] + kind: Literal["per_ad_spend"] = "per_ad_spend" value: Annotated[ float, Field(description="Target return ratio (e.g., 4.0 means $4 of value per $1 spent)", gt=0.0), @@ -2399,7 +2399,7 @@ class Target9(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["maximize_value"] + kind: Literal["maximize_value"] = "maximize_value" class PostClick(Suppress): @@ -2432,7 +2432,7 @@ class OptimizationGoals3(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["event"] + kind: Literal["event"] = "event" event_sources: Annotated[ list[EventSource], Field( @@ -2817,7 +2817,7 @@ class SignalId(AdCPBaseModel): Field( description="Discriminator indicating this signal is from a data provider's published catalog" ), - ] + ] = "catalog" data_provider_domain: Annotated[ str, Field( @@ -2843,7 +2843,7 @@ class SignalId2(AdCPBaseModel): Field( description="Discriminator indicating this signal is native to the agent (not from a data provider catalog)" ), - ] + ] = "agent" agent_url: Annotated[ AnyUrl, Field( @@ -2865,12 +2865,14 @@ class AudienceTargeting(AdCPBaseModel): ) type: Annotated[ Literal["signal"], Field(description="Discriminator for signal-based selectors") - ] + ] = "signal" signal_id: Annotated[ SignalId | SignalId2, Field(description="The signal to target", discriminator="source", title="Signal ID"), ] - value_type: Annotated[Literal["binary"], Field(description="Discriminator for binary signals")] + value_type: Annotated[ + Literal["binary"], Field(description="Discriminator for binary signals") + ] = "binary" value: Annotated[ bool, Field( @@ -2885,14 +2887,14 @@ class AudienceTargeting1(AdCPBaseModel): ) type: Annotated[ Literal["signal"], Field(description="Discriminator for signal-based selectors") - ] + ] = "signal" signal_id: Annotated[ SignalId | SignalId2, Field(description="The signal to target", discriminator="source", title="Signal ID"), ] value_type: Annotated[ Literal["categorical"], Field(description="Discriminator for categorical signals") - ] + ] = "categorical" values: Annotated[ list[str], Field( @@ -2908,14 +2910,14 @@ class AudienceTargeting2(AdCPBaseModel): ) type: Annotated[ Literal["signal"], Field(description="Discriminator for signal-based selectors") - ] + ] = "signal" signal_id: Annotated[ SignalId | SignalId2, Field(description="The signal to target", discriminator="source", title="Signal ID"), ] value_type: Annotated[ Literal["numeric"], Field(description="Discriminator for numeric signals") - ] + ] = "numeric" min_value: Annotated[ float | None, Field( @@ -2936,7 +2938,7 @@ class AudienceTargeting3(AdCPBaseModel): ) type: Annotated[ Literal["description"], Field(description="Discriminator for description-based selectors") - ] + ] = "description" description: Annotated[ str, Field( @@ -3327,7 +3329,7 @@ class CreateMediaBuyResponse6(AdCPBaseModel): Field( description="Task-level status literal. Discriminates this async envelope from the synchronous success shape, whose status field carries a MediaBuyStatus value (pending_creatives, pending_start, active). See task-status.json for the full task-status enum." ), - ] + ] = "submitted" task_id: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/bundled/media_buy/get_media_buy_delivery_request.py b/src/adcp/types/generated_poc/bundled/media_buy/get_media_buy_delivery_request.py index 821a7fd8c..500f58f99 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/get_media_buy_delivery_request.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/get_media_buy_delivery_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/get_media_buy_delivery_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/get_media_buy_delivery_response.py b/src/adcp/types/generated_poc/bundled/media_buy/get_media_buy_delivery_response.py index 671126a91..ebaaacf7d 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/get_media_buy_delivery_response.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/get_media_buy_delivery_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/get_media_buy_delivery_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/get_media_buys_request.py b/src/adcp/types/generated_poc/bundled/media_buy/get_media_buys_request.py index 2c1f36bdb..56c81e238 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/get_media_buys_request.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/get_media_buys_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/get_media_buys_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/get_media_buys_response.py b/src/adcp/types/generated_poc/bundled/media_buy/get_media_buys_response.py index 8fbffd69b..ab62ea810 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/get_media_buys_response.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/get_media_buys_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/get_media_buys_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/get_products_request.py b/src/adcp/types/generated_poc/bundled/media_buy/get_products_request.py index 031872347..b39f3ef7e 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/get_products_request.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/get_products_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/get_products_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -27,7 +27,7 @@ class Refine(AdCPBaseModel): Field( description="Change scoped to the overall request — direction for the selection as a whole." ), - ] + ] = "request" ask: Annotated[ str, Field( @@ -43,20 +43,22 @@ class Action(Enum): more_like_this = "more_like_this" -class Refine4(AdCPBaseModel): +class Refine6(AdCPBaseModel): model_config = ConfigDict( extra="forbid", ) - scope: Annotated[Literal["product"], Field(description="Change scoped to a specific product.")] - id: Annotated[ + scope: Annotated[ + Literal["product"], Field(description="Change scoped to a specific product.") + ] = "product" + product_id: Annotated[ str, Field(description="Product ID from a previous get_products response.", min_length=1) ] action: Annotated[ - Action, + Action | None, Field( - description="'include': return this product with updated pricing and data. 'omit': exclude this product from the response. 'more_like_this': find additional products similar to this one (the original is also returned)." + description="'include' (default): return this product with updated pricing and data. 'omit': exclude this product from the response. 'more_like_this': find additional products similar to this one (the original is also returned). Optional — when omitted, the seller treats the entry as action: 'include'." ), - ] + ] = Action.include ask: Annotated[ str | None, Field( @@ -72,22 +74,22 @@ class Action5(Enum): finalize = "finalize" -class Refine5(AdCPBaseModel): +class Refine7(AdCPBaseModel): model_config = ConfigDict( extra="forbid", ) scope: Annotated[ Literal["proposal"], Field(description="Change scoped to a specific proposal.") - ] - id: Annotated[ + ] = "proposal" + proposal_id: Annotated[ str, Field(description="Proposal ID from a previous get_products response.", min_length=1) ] action: Annotated[ - Action5, + Action5 | None, Field( - description="'include': return this proposal with updated allocations and pricing. 'omit': exclude this proposal from the response. 'finalize': request firm pricing and inventory hold — transitions a draft proposal to committed with an expires_at hold window. May trigger seller-side approval (HITL). The buyer should not set a time_budget for finalize requests — they represent a commitment to wait for the result." + description="'include' (default): return this proposal with updated allocations and pricing. 'omit': exclude this proposal from the response. 'finalize': request firm pricing and inventory hold — transitions a draft proposal to committed with an expires_at hold window. May trigger seller-side approval (HITL). The buyer should not set a time_budget for finalize requests — they represent a commitment to wait for the result. Optional — when omitted, the seller treats the entry as action: 'include'." ), - ] + ] = Action5.include ask: Annotated[ str | None, Field( @@ -97,6 +99,16 @@ class Refine5(AdCPBaseModel): ] = None +class Refine4(RootModel[Refine | Refine6 | Refine7]): + root: Annotated[Refine | Refine6 | Refine7, Field(discriminator="scope")] + + def __getattr__(self, name: str) -> Any: + """Proxy attribute access to the wrapped type.""" + if name.startswith("_"): + raise AttributeError(name) + return getattr(self.root, name) + + class DataSubjectContestation(AdCPBaseModel): model_config = ConfigDict( extra="forbid", @@ -727,7 +739,7 @@ class SignalId(AdCPBaseModel): Field( description="Discriminator indicating this signal is from a data provider's published catalog" ), - ] + ] = "catalog" data_provider_domain: Annotated[ str, Field( @@ -753,7 +765,7 @@ class SignalId9(AdCPBaseModel): Field( description="Discriminator indicating this signal is native to the agent (not from a data provider catalog)" ), - ] + ] = "agent" agent_url: Annotated[ AnyUrl, Field( @@ -777,7 +789,9 @@ class SignalTargeting1(AdCPBaseModel): SignalId | SignalId9, Field(description="The signal to target", discriminator="source", title="Signal ID"), ] - value_type: Annotated[Literal["binary"], Field(description="Discriminator for binary signals")] + value_type: Annotated[ + Literal["binary"], Field(description="Discriminator for binary signals") + ] = "binary" value: Annotated[ bool, Field( @@ -796,7 +810,7 @@ class SignalTargeting2(AdCPBaseModel): ] value_type: Annotated[ Literal["categorical"], Field(description="Discriminator for categorical signals") - ] + ] = "categorical" values: Annotated[ list[str], Field( @@ -816,7 +830,7 @@ class SignalTargeting3(AdCPBaseModel): ] value_type: Annotated[ Literal["numeric"], Field(description="Discriminator for numeric signals") - ] + ] = "numeric" min_value: Annotated[ float | None, Field( @@ -1407,7 +1421,7 @@ class GetProductsRequest(AdCPBaseModel): ), ] = None refine: Annotated[ - list[Refine | Refine4 | Refine5] | None, + list[Refine4] | None, Field( description="Array of change requests for iterating on products and proposals from a previous get_products response. Each entry declares a scope (request, product, or proposal) and what the buyer is asking for. Only valid when buying_mode is 'refine'. The seller responds to each entry via refinement_applied in the response, matched by position.", min_length=1, diff --git a/src/adcp/types/generated_poc/bundled/media_buy/get_products_response.py b/src/adcp/types/generated_poc/bundled/media_buy/get_products_response.py index c3276f016..c65af0aaf 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/get_products_response.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/get_products_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/get_products_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -27,7 +27,7 @@ class PublisherProperties1(AdCPBaseModel): Field( description="Discriminator indicating all properties from this publisher are included" ), - ] + ] = "all" class PropertyId(RootModel[str]): @@ -56,7 +56,7 @@ class PublisherProperties2(AdCPBaseModel): selection_type: Annotated[ Literal["by_id"], Field(description="Discriminator indicating selection by specific property IDs"), - ] + ] = "by_id" property_ids: Annotated[ list[PropertyId], Field(description="Specific property IDs from the publisher's adagents.json", min_length=1), @@ -88,7 +88,7 @@ class PublisherProperties3(AdCPBaseModel): ] selection_type: Annotated[ Literal["by_tag"], Field(description="Discriminator indicating selection by property tags") - ] + ] = "by_tag" property_tags: Annotated[ list[PropertyTag], Field( @@ -395,7 +395,9 @@ class PricingOptions(AdCPBaseModel): pricing_option_id: Annotated[ str, Field(description="Unique identifier for this pricing option within the product") ] - pricing_model: Annotated[Literal["cpm"], Field(description="Cost per 1,000 impressions")] + pricing_model: Annotated[Literal["cpm"], Field(description="Cost per 1,000 impressions")] = ( + "cpm" + ) currency: Annotated[ str, Field( @@ -491,7 +493,7 @@ class PricingOptions1(AdCPBaseModel): ] pricing_model: Annotated[ Literal["vcpm"], Field(description="Cost per 1,000 viewable impressions (MRC standard)") - ] + ] = "vcpm" currency: Annotated[ str, Field( @@ -585,7 +587,7 @@ class PricingOptions2(AdCPBaseModel): pricing_option_id: Annotated[ str, Field(description="Unique identifier for this pricing option within the product") ] - pricing_model: Annotated[Literal["cpc"], Field(description="Cost per click")] + pricing_model: Annotated[Literal["cpc"], Field(description="Cost per click")] = "cpc" currency: Annotated[ str, Field( @@ -681,7 +683,7 @@ class PricingOptions3(AdCPBaseModel): ] pricing_model: Annotated[ Literal["cpcv"], Field(description="Cost per completed view (100% completion)") - ] + ] = "cpcv" currency: Annotated[ str, Field( @@ -800,7 +802,9 @@ class PricingOptions4(AdCPBaseModel): pricing_option_id: Annotated[ str, Field(description="Unique identifier for this pricing option within the product") ] - pricing_model: Annotated[Literal["cpv"], Field(description="Cost per view at threshold")] + pricing_model: Annotated[Literal["cpv"], Field(description="Cost per view at threshold")] = ( + "cpv" + ) currency: Annotated[ str, Field( @@ -928,7 +932,9 @@ class PricingOptions5(AdCPBaseModel): pricing_option_id: Annotated[ str, Field(description="Unique identifier for this pricing option within the product") ] - pricing_model: Annotated[Literal["cpp"], Field(description="Cost per Gross Rating Point")] + pricing_model: Annotated[Literal["cpp"], Field(description="Cost per Gross Rating Point")] = ( + "cpp" + ) currency: Annotated[ str, Field( @@ -1025,7 +1031,7 @@ class PricingOptions6(AdCPBaseModel): ] pricing_model: Annotated[ Literal["cpa"], Field(description="Cost per acquisition (conversion event)") - ] + ] = "cpa" event_type: Annotated[ EventType, Field( @@ -1083,7 +1089,7 @@ class Parameters5(AdCPBaseModel): ) type: Annotated[ Literal["dooh"], Field(description="Discriminator identifying this as DOOH parameters") - ] + ] = "dooh" sov_percentage: Annotated[ float | None, Field(description="Guaranteed share of voice as a percentage (0-100)", ge=0.0, le=100.0), @@ -1155,7 +1161,7 @@ class PricingOptions7(AdCPBaseModel): ] pricing_model: Annotated[ Literal["flat_rate"], Field(description="Fixed cost regardless of delivery volume") - ] + ] = "flat_rate" currency: Annotated[ str, Field( @@ -1282,7 +1288,7 @@ class PricingOptions8(AdCPBaseModel): pricing_model: Annotated[ Literal["time"], Field(description="Cost per time unit - rate scales with campaign duration"), - ] + ] = "time" currency: Annotated[ str, Field( @@ -2363,7 +2369,7 @@ class DataProviderSignals1(AdCPBaseModel): Field( description="Discriminator indicating all signals from this data provider are included" ), - ] + ] = "all" class SignalId(RootModel[str]): @@ -2384,7 +2390,7 @@ class DataProviderSignals2(AdCPBaseModel): selection_type: Annotated[ Literal["by_id"], Field(description="Discriminator indicating selection by specific signal IDs"), - ] + ] = "by_id" signal_ids: Annotated[ list[SignalId], Field(description="Specific signal IDs from the data provider's catalog", min_length=1), @@ -2408,7 +2414,7 @@ class DataProviderSignals3(AdCPBaseModel): ] selection_type: Annotated[ Literal["by_tag"], Field(description="Discriminator indicating selection by signal tags") - ] + ] = "by_tag" signal_tags: Annotated[ list[SignalTag], Field( @@ -2732,7 +2738,7 @@ class Collection(AdCPBaseModel): ] -class Status17(Enum): +class Status19(Enum): scheduled = "scheduled" tentative = "tentative" live = "live" @@ -2956,7 +2962,7 @@ class Installment(AdCPBaseModel): AwareDatetime | None, Field(description="When the installment airs or publishes (ISO 8601)") ] = None status: Annotated[ - Status17 | None, + Status19 | None, Field(description="Lifecycle status of the installment", title="Installment Status"), ] = None duration_seconds: Annotated[ @@ -4419,36 +4425,72 @@ class Error(AdCPBaseModel): ] = None -class Scope(Enum): - request = "request" - product = "product" - proposal = "proposal" - - -class Status18(Enum): +class Status20(Enum): applied = "applied" partial = "partial" unable = "unable" -class RefinementAppliedItem(AdCPBaseModel): +class RefinementApplied(AdCPBaseModel): model_config = ConfigDict( extra="forbid", ) scope: Annotated[ - Scope | None, + Literal["request"], + Field(description="Echoes scope 'request' from the corresponding refine entry."), + ] = "request" + status: Annotated[ + Status20, Field( - description="Echoes the scope from the corresponding refine entry. Allows orchestrators to cross-validate alignment." + description="'applied': the ask was fulfilled. 'partial': the ask was partially fulfilled — see notes for details. 'unable': the seller could not fulfill the ask — see notes for why." + ), + ] + notes: Annotated[ + str | None, + Field( + description="Seller explanation of what was done, what couldn't be done, or why. Recommended when status is 'partial' or 'unable'." ), ] = None - id: Annotated[ + + +class RefinementApplied6(AdCPBaseModel): + model_config = ConfigDict( + extra="forbid", + ) + scope: Annotated[ + Literal["product"], + Field(description="Echoes scope 'product' from the corresponding refine entry."), + ] = "product" + product_id: Annotated[ + str, Field(description="Echoes product_id from the corresponding refine entry.") + ] + status: Annotated[ + Status20, + Field( + description="'applied': the ask was fulfilled. 'partial': the ask was partially fulfilled — see notes for details. 'unable': the seller could not fulfill the ask — see notes for why." + ), + ] + notes: Annotated[ str | None, Field( - description="Echoes the id from the corresponding refine entry (for product and proposal scopes)." + description="Seller explanation of what was done, what couldn't be done, or why. Recommended when status is 'partial' or 'unable'." ), ] = None + + +class RefinementApplied7(AdCPBaseModel): + model_config = ConfigDict( + extra="forbid", + ) + scope: Annotated[ + Literal["proposal"], + Field(description="Echoes scope 'proposal' from the corresponding refine entry."), + ] = "proposal" + proposal_id: Annotated[ + str, Field(description="Echoes proposal_id from the corresponding refine entry.") + ] status: Annotated[ - Status18, + Status20, Field( description="'applied': the ask was fulfilled. 'partial': the ask was partially fulfilled — see notes for details. 'unable': the seller could not fulfill the ask — see notes for why." ), @@ -4461,7 +4503,19 @@ class RefinementAppliedItem(AdCPBaseModel): ] = None -class Scope5(Enum): +class RefinementApplied4(RootModel[RefinementApplied | RefinementApplied6 | RefinementApplied7]): + root: Annotated[ + RefinementApplied | RefinementApplied6 | RefinementApplied7, Field(discriminator="scope") + ] + + def __getattr__(self, name: str) -> Any: + """Proxy attribute access to the wrapped type.""" + if name.startswith("_"): + raise AttributeError(name) + return getattr(self.root, name) + + +class Scope(Enum): products = "products" pricing = "pricing" forecast = "forecast" @@ -4477,7 +4531,7 @@ class IncompleteItem(AdCPBaseModel): extra="forbid", ) scope: Annotated[ - Scope5, + Scope, Field( description="'products': not all inventory sources were searched. 'pricing': products returned but pricing is absent or unconfirmed. 'forecast': products returned but forecast data is absent. 'proposals': proposals were not generated or are incomplete." ), @@ -4543,9 +4597,9 @@ class GetProductsResponse(AdCPBaseModel): ), ] = None refinement_applied: Annotated[ - list[RefinementAppliedItem] | None, + list[RefinementApplied4] | None, Field( - description="Seller's response to each change request in the refine array, matched by position. Each entry acknowledges whether the corresponding ask was applied, partially applied, or unable to be fulfilled. MUST contain the same number of entries in the same order as the request's refine array. Only present when the request used buying_mode: 'refine'." + description="Seller's response to each change request in the refine array, matched by position. Each entry acknowledges whether the corresponding ask was applied, partially applied, or unable to be fulfilled. MUST contain the same number of entries in the same order as the request's refine array. Only present when the request used buying_mode: 'refine'. Each entry MUST echo the request entry's scope and — for product and proposal scopes — the matching id field (product_id or proposal_id), so orchestrators can cross-validate alignment." ), ] = None incomplete: Annotated[ diff --git a/src/adcp/types/generated_poc/bundled/media_buy/list_creative_formats_request.py b/src/adcp/types/generated_poc/bundled/media_buy/list_creative_formats_request.py index 1690461a4..b9a57dddb 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/list_creative_formats_request.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/list_creative_formats_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/list_creative_formats_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/list_creative_formats_response.py b/src/adcp/types/generated_poc/bundled/media_buy/list_creative_formats_response.py index 72e843e47..00f6854a3 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/list_creative_formats_response.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/list_creative_formats_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/list_creative_formats_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -1260,7 +1260,7 @@ class PricingOption161(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["cpm"] + model: Literal["cpm"] = "cpm" cpm: Annotated[float, Field(description="Cost per thousand impressions", ge=0.0)] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] ext: Annotated[ @@ -1276,7 +1276,7 @@ class PricingOption162(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["percent_of_media"] + model: Literal["percent_of_media"] = "percent_of_media" percent: Annotated[ float, Field(description="Percentage of media spend, e.g. 15 = 15%", ge=0.0, le=100.0) ] @@ -1311,7 +1311,7 @@ class PricingOption163(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["flat_fee"] + model: Literal["flat_fee"] = "flat_fee" amount: Annotated[float, Field(description="Fixed charge for the billing period", ge=0.0)] period: Annotated[Period, Field(description="Billing period for the flat fee.")] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] @@ -1328,7 +1328,7 @@ class PricingOption164(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["per_unit"] + model: Literal["per_unit"] = "per_unit" unit: Annotated[ str, Field( @@ -1363,7 +1363,7 @@ class PricingOption165(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["custom"] + model: Literal["custom"] = "custom" description: Annotated[ str, Field( @@ -1542,7 +1542,7 @@ class ScalarBinding(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["scalar"] + kind: Literal["scalar"] = "scalar" asset_id: Annotated[ str, Field( @@ -1568,7 +1568,7 @@ class AssetPoolBinding(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["asset_pool"] + kind: Literal["asset_pool"] = "asset_pool" asset_id: Annotated[ str, Field( @@ -1725,7 +1725,7 @@ class BaseIndividualAsset(AdCPBaseModel): item_type: Annotated[ Literal["individual"], Field(description="Discriminator indicating this is an individual asset"), - ] + ] = "individual" asset_id: Annotated[ str, Field( @@ -1901,7 +1901,7 @@ class FieldBindings(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["catalog_group"] + kind: Literal["catalog_group"] = "catalog_group" format_group_id: Annotated[ str, Field(description="The asset_group_id of a repeatable_group in the format's assets array."), @@ -2130,7 +2130,7 @@ class Assets173(AdCPBaseModel): item_type: Annotated[ Literal["repeatable_group"], Field(description="Discriminator indicating this is a repeatable asset group"), - ] + ] = "repeatable_group" asset_group_id: Annotated[ str, Field(description="Identifier for this asset group (e.g., 'product', 'slide', 'card')") ] diff --git a/src/adcp/types/generated_poc/bundled/media_buy/log_event_request.py b/src/adcp/types/generated_poc/bundled/media_buy/log_event_request.py index b33d0183f..8ac82ff28 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/log_event_request.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/log_event_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/log_event_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/log_event_response.py b/src/adcp/types/generated_poc/bundled/media_buy/log_event_response.py index 339a3b4d2..238158d28 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/log_event_response.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/log_event_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/log_event_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/package_request.py b/src/adcp/types/generated_poc/bundled/media_buy/package_request.py index 401344add..e5526ec35 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/package_request.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/package_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/package_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -431,7 +431,7 @@ class Target(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["cost_per"] + kind: Literal["cost_per"] = "cost_per" value: Annotated[ float, Field(description="Target cost per metric unit in the buy currency", gt=0.0) ] @@ -441,7 +441,7 @@ class Target16(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["threshold_rate"] + kind: Literal["threshold_rate"] = "threshold_rate" value: Annotated[ float, Field( @@ -455,7 +455,7 @@ class OptimizationGoals(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["metric"] + kind: Literal["metric"] = "metric" metric: Annotated[ Metric, Field( @@ -538,7 +538,7 @@ class Target17(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["cost_per"] + kind: Literal["cost_per"] = "cost_per" value: Annotated[float, Field(description="Target cost per event in the buy currency", gt=0.0)] @@ -546,7 +546,7 @@ class Target18(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["per_ad_spend"] + kind: Literal["per_ad_spend"] = "per_ad_spend" value: Annotated[ float, Field(description="Target return ratio (e.g., 4.0 means $4 of value per $1 spent)", gt=0.0), @@ -557,7 +557,7 @@ class Target19(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["maximize_value"] + kind: Literal["maximize_value"] = "maximize_value" class PostClick(Window): @@ -590,7 +590,7 @@ class OptimizationGoals5(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["event"] + kind: Literal["event"] = "event" event_sources: Annotated[ list[EventSource], Field( @@ -2033,6 +2033,12 @@ class Assets(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -2238,6 +2244,12 @@ class Assets230(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -2451,6 +2463,12 @@ class Assets231(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -2659,11 +2677,12 @@ class Assets232(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -2691,6 +2710,11 @@ class Assets232(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy141(DeclaredBy): @@ -2821,11 +2845,12 @@ class Assets233(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -2853,6 +2878,11 @@ class Assets233(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy142(DeclaredBy): @@ -2983,6 +3013,12 @@ class Assets234(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -3130,7 +3166,18 @@ class Assets235(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -3296,6 +3343,12 @@ class Assets236(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -3445,6 +3498,12 @@ class Assets237(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -3693,6 +3752,12 @@ class Assets238(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -3855,6 +3920,12 @@ class Assets239(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -4027,11 +4098,12 @@ class Assets240(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -4055,6 +4127,11 @@ class Assets240(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy149(DeclaredBy): @@ -4185,11 +4262,12 @@ class Assets241(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -4213,6 +4291,11 @@ class Assets241(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class MarkdownFlavor(Enum): @@ -4224,6 +4307,12 @@ class Assets242(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["markdown"], + Field( + description="Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + ), + ] = "markdown" content: Annotated[ str, Field( @@ -4406,6 +4495,12 @@ class Assets243(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class FeedFieldMapping11(FeedFieldMapping): @@ -4513,6 +4608,12 @@ class Assets244(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class Input(AdCPBaseModel): @@ -4718,7 +4819,9 @@ class Creative(AdCPBaseModel): | Assets243 | Assets244, ], - Field(description="Assets required by the format, keyed by asset_id"), + Field( + description="Assets required by the format, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema." + ), ] inputs: Annotated[ list[Input] | None, diff --git a/src/adcp/types/generated_poc/bundled/media_buy/provide_performance_feedback_request.py b/src/adcp/types/generated_poc/bundled/media_buy/provide_performance_feedback_request.py index 0a981ba41..1c6f32383 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/provide_performance_feedback_request.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/provide_performance_feedback_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/provide_performance_feedback_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/provide_performance_feedback_response.py b/src/adcp/types/generated_poc/bundled/media_buy/provide_performance_feedback_response.py index c2d479a71..d34e5e97c 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/provide_performance_feedback_response.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/provide_performance_feedback_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/provide_performance_feedback_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/sync_audiences_request.py b/src/adcp/types/generated_poc/bundled/media_buy/sync_audiences_request.py index 68b8e6b13..0de780b70 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/sync_audiences_request.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/sync_audiences_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/sync_audiences_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/sync_audiences_response.py b/src/adcp/types/generated_poc/bundled/media_buy/sync_audiences_response.py index 0223389f0..460769979 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/sync_audiences_response.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/sync_audiences_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/sync_audiences_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/sync_catalogs_request.py b/src/adcp/types/generated_poc/bundled/media_buy/sync_catalogs_request.py index b911871f5..4f76a2962 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/sync_catalogs_request.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/sync_catalogs_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/sync_catalogs_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/sync_catalogs_response.py b/src/adcp/types/generated_poc/bundled/media_buy/sync_catalogs_response.py index 0bc7ed8fc..536f58a6b 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/sync_catalogs_response.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/sync_catalogs_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/sync_catalogs_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/sync_event_sources_request.py b/src/adcp/types/generated_poc/bundled/media_buy/sync_event_sources_request.py index e093bce17..10b5416f4 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/sync_event_sources_request.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/sync_event_sources_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/sync_event_sources_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/sync_event_sources_response.py b/src/adcp/types/generated_poc/bundled/media_buy/sync_event_sources_response.py index 6cba2b75a..a49ebe991 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/sync_event_sources_response.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/sync_event_sources_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/sync_event_sources_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/media_buy/update_media_buy_request.py b/src/adcp/types/generated_poc/bundled/media_buy/update_media_buy_request.py index f1ab4e845..f41a8df46 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/update_media_buy_request.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/update_media_buy_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/update_media_buy_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -486,7 +486,7 @@ class Target(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["cost_per"] + kind: Literal["cost_per"] = "cost_per" value: Annotated[ float, Field(description="Target cost per metric unit in the buy currency", gt=0.0) ] @@ -496,7 +496,7 @@ class Target21(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["threshold_rate"] + kind: Literal["threshold_rate"] = "threshold_rate" value: Annotated[ float, Field( @@ -510,7 +510,7 @@ class OptimizationGoals(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["metric"] + kind: Literal["metric"] = "metric" metric: Annotated[ Metric, Field( @@ -593,7 +593,7 @@ class Target22(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["cost_per"] + kind: Literal["cost_per"] = "cost_per" value: Annotated[float, Field(description="Target cost per event in the buy currency", gt=0.0)] @@ -601,7 +601,7 @@ class Target23(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["per_ad_spend"] + kind: Literal["per_ad_spend"] = "per_ad_spend" value: Annotated[ float, Field(description="Target return ratio (e.g., 4.0 means $4 of value per $1 spent)", gt=0.0), @@ -612,7 +612,7 @@ class Target24(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["maximize_value"] + kind: Literal["maximize_value"] = "maximize_value" class PostClick(Window): @@ -645,7 +645,7 @@ class OptimizationGoals7(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["event"] + kind: Literal["event"] = "event" event_sources: Annotated[ list[EventSource], Field( @@ -1937,6 +1937,12 @@ class Assets(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -2142,6 +2148,12 @@ class Assets318(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -2355,6 +2367,12 @@ class Assets319(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -2563,11 +2581,12 @@ class Assets320(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -2595,6 +2614,11 @@ class Assets320(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy222(DeclaredBy): @@ -2725,11 +2749,12 @@ class Assets321(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -2757,6 +2782,11 @@ class Assets321(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy223(DeclaredBy): @@ -2887,6 +2917,12 @@ class Assets322(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -3034,7 +3070,18 @@ class Assets323(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -3200,6 +3247,12 @@ class Assets324(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -3349,6 +3402,12 @@ class Assets325(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -3597,6 +3656,12 @@ class Assets326(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -3759,6 +3824,12 @@ class Assets327(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -3931,11 +4002,12 @@ class Assets328(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -3959,6 +4031,11 @@ class Assets328(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy230(DeclaredBy): @@ -4089,11 +4166,12 @@ class Assets329(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -4117,6 +4195,11 @@ class Assets329(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class MarkdownFlavor(Enum): @@ -4128,6 +4211,12 @@ class Assets330(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["markdown"], + Field( + description="Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + ), + ] = "markdown" content: Annotated[ str, Field( @@ -4310,6 +4399,12 @@ class Assets331(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class FeedFieldMapping18(FeedFieldMapping): @@ -4417,6 +4512,12 @@ class Assets332(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class Input(AdCPBaseModel): @@ -4622,7 +4723,9 @@ class Creative(AdCPBaseModel): | Assets331 | Assets332, ], - Field(description="Assets required by the format, keyed by asset_id"), + Field( + description="Assets required by the format, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema." + ), ] inputs: Annotated[ list[Input] | None, @@ -5103,7 +5206,7 @@ class OptimizationGoals8(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["metric"] + kind: Literal["metric"] = "metric" metric: Annotated[ Metric, Field( @@ -5190,7 +5293,7 @@ class OptimizationGoals9(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["event"] + kind: Literal["event"] = "event" event_sources: Annotated[ list[EventSource9], Field( @@ -6136,6 +6239,12 @@ class Assets333(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] @@ -6280,6 +6389,12 @@ class Assets334(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] @@ -6493,6 +6608,12 @@ class Assets335(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) @@ -6658,11 +6779,12 @@ class Assets336(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -6690,6 +6812,11 @@ class Assets336(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class DeclaredBy236(DeclaredBy): @@ -6820,11 +6947,12 @@ class Assets337(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ VastVersion | None, Field(description="VAST specification version", title="VAST Version") ] = None @@ -6852,6 +6980,11 @@ class Assets337(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class DeclaredBy237(DeclaredBy): @@ -6982,6 +7115,12 @@ class Assets338(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" content: Annotated[str, Field(description="Text content")] language: Annotated[str | None, Field(description="Language code (e.g., 'en', 'es', 'fr')")] = ( None @@ -7123,7 +7262,18 @@ class Assets339(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] url_type: Annotated[ UrlType | None, Field( @@ -7271,6 +7421,12 @@ class Assets340(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ @@ -7414,6 +7570,12 @@ class Assets341(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ ModuleType | None, @@ -7564,6 +7726,12 @@ class Assets342(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[Method | None, Field(description="HTTP method", title="HTTP Method")] = ( Method.POST @@ -7726,6 +7894,12 @@ class Assets343(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") @@ -7867,11 +8041,12 @@ class Assets344(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -7895,6 +8070,11 @@ class Assets344(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DeclaredBy244(DeclaredBy): @@ -8025,11 +8205,12 @@ class Assets345(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ DaastVersion | None, Field(description="DAAST specification version", title="DAAST Version") ] = None @@ -8053,6 +8234,11 @@ class Assets345(AdCPBaseModel): title="Provenance", ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class Assets346(Assets330): @@ -8170,6 +8356,12 @@ class Assets347(AdCPBaseModel): description="Regulatory and legal compliance requirements for this campaign. Campaign-specific, regional, and product-based — distinct from brand-level disclaimers in brand.json." ), ] = None + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" class FeedFieldMapping20(FeedFieldMapping): @@ -8277,6 +8469,12 @@ class Assets348(AdCPBaseModel): min_length=1, ), ] = None + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" class IndustryIdentifier12(IndustryIdentifier): @@ -8440,7 +8638,9 @@ class Creative12(AdCPBaseModel): | Assets347 | Assets348, ], - Field(description="Assets required by the format, keyed by asset_id"), + Field( + description="Assets required by the format, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema." + ), ] inputs: Annotated[ list[Input] | None, diff --git a/src/adcp/types/generated_poc/bundled/media_buy/update_media_buy_response.py b/src/adcp/types/generated_poc/bundled/media_buy/update_media_buy_response.py index 5471aec70..037c7e403 100644 --- a/src/adcp/types/generated_poc/bundled/media_buy/update_media_buy_response.py +++ b/src/adcp/types/generated_poc/bundled/media_buy/update_media_buy_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/media_buy/update_media_buy_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -1852,7 +1852,7 @@ class Target(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["cost_per"] + kind: Literal["cost_per"] = "cost_per" value: Annotated[ float, Field(description="Target cost per metric unit in the buy currency", gt=0.0) ] @@ -1862,7 +1862,7 @@ class Target31(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["threshold_rate"] + kind: Literal["threshold_rate"] = "threshold_rate" value: Annotated[ float, Field( @@ -1876,7 +1876,7 @@ class OptimizationGoals(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["metric"] + kind: Literal["metric"] = "metric" metric: Annotated[ Metric13, Field( @@ -1959,7 +1959,7 @@ class Target32(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["cost_per"] + kind: Literal["cost_per"] = "cost_per" value: Annotated[float, Field(description="Target cost per event in the buy currency", gt=0.0)] @@ -1967,7 +1967,7 @@ class Target33(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["per_ad_spend"] + kind: Literal["per_ad_spend"] = "per_ad_spend" value: Annotated[ float, Field(description="Target return ratio (e.g., 4.0 means $4 of value per $1 spent)", gt=0.0), @@ -1978,7 +1978,7 @@ class Target34(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["maximize_value"] + kind: Literal["maximize_value"] = "maximize_value" class PostClick(Suppress): @@ -2011,7 +2011,7 @@ class OptimizationGoals11(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["event"] + kind: Literal["event"] = "event" event_sources: Annotated[ list[EventSource], Field( diff --git a/src/adcp/types/generated_poc/bundled/property/create_property_list_request.py b/src/adcp/types/generated_poc/bundled/property/create_property_list_request.py index 51178ecf8..01c4e536d 100644 --- a/src/adcp/types/generated_poc/bundled/property/create_property_list_request.py +++ b/src/adcp/types/generated_poc/bundled/property/create_property_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/property/create_property_list_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -125,7 +125,7 @@ class BaseProperties1(AdCPBaseModel): selection_type: Annotated[ Literal["publisher_tags"], Field(description="Discriminator indicating selection by property tags within a publisher"), - ] + ] = "publisher_tags" publisher_domain: Annotated[ str, Field( @@ -163,7 +163,7 @@ class BaseProperties2(AdCPBaseModel): Field( description="Discriminator indicating selection by specific property IDs within a publisher" ), - ] + ] = "publisher_ids" publisher_domain: Annotated[ str, Field( @@ -235,7 +235,7 @@ class BaseProperties3(AdCPBaseModel): selection_type: Annotated[ Literal["identifiers"], Field(description="Discriminator indicating selection by direct identifiers"), - ] + ] = "identifiers" identifiers: Annotated[ list[Identifier], Field(description="Direct property identifiers (domains, app IDs, etc.)", min_length=1), diff --git a/src/adcp/types/generated_poc/bundled/property/create_property_list_response.py b/src/adcp/types/generated_poc/bundled/property/create_property_list_response.py index b7f076ba6..00cb2cf56 100644 --- a/src/adcp/types/generated_poc/bundled/property/create_property_list_response.py +++ b/src/adcp/types/generated_poc/bundled/property/create_property_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/property/create_property_list_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -125,7 +125,7 @@ class BaseProperties(AdCPBaseModel): selection_type: Annotated[ Literal["publisher_tags"], Field(description="Discriminator indicating selection by property tags within a publisher"), - ] + ] = "publisher_tags" publisher_domain: Annotated[ str, Field( @@ -163,7 +163,7 @@ class BaseProperties6(AdCPBaseModel): Field( description="Discriminator indicating selection by specific property IDs within a publisher" ), - ] + ] = "publisher_ids" publisher_domain: Annotated[ str, Field( @@ -235,7 +235,7 @@ class BaseProperties7(AdCPBaseModel): selection_type: Annotated[ Literal["identifiers"], Field(description="Discriminator indicating selection by direct identifiers"), - ] + ] = "identifiers" identifiers: Annotated[ list[Identifier], Field(description="Direct property identifiers (domains, app IDs, etc.)", min_length=1), @@ -423,7 +423,7 @@ class PricingOption1(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["cpm"] + model: Literal["cpm"] = "cpm" cpm: Annotated[float, Field(description="Cost per thousand impressions", ge=0.0)] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] ext: Annotated[ @@ -439,7 +439,7 @@ class PricingOption2(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["percent_of_media"] + model: Literal["percent_of_media"] = "percent_of_media" percent: Annotated[ float, Field(description="Percentage of media spend, e.g. 15 = 15%", ge=0.0, le=100.0) ] @@ -474,7 +474,7 @@ class PricingOption3(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["flat_fee"] + model: Literal["flat_fee"] = "flat_fee" amount: Annotated[float, Field(description="Fixed charge for the billing period", ge=0.0)] period: Annotated[Period, Field(description="Billing period for the flat fee.")] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] @@ -491,7 +491,7 @@ class PricingOption4(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["per_unit"] + model: Literal["per_unit"] = "per_unit" unit: Annotated[ str, Field( @@ -526,7 +526,7 @@ class PricingOption5(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["custom"] + model: Literal["custom"] = "custom" description: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/bundled/property/delete_property_list_request.py b/src/adcp/types/generated_poc/bundled/property/delete_property_list_request.py index 0344378bd..d14794a25 100644 --- a/src/adcp/types/generated_poc/bundled/property/delete_property_list_request.py +++ b/src/adcp/types/generated_poc/bundled/property/delete_property_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/property/delete_property_list_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/property/delete_property_list_response.py b/src/adcp/types/generated_poc/bundled/property/delete_property_list_response.py index f2dcbb882..d49da1114 100644 --- a/src/adcp/types/generated_poc/bundled/property/delete_property_list_response.py +++ b/src/adcp/types/generated_poc/bundled/property/delete_property_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/property/delete_property_list_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/property/get_property_list_request.py b/src/adcp/types/generated_poc/bundled/property/get_property_list_request.py index d014e885d..099a8aeef 100644 --- a/src/adcp/types/generated_poc/bundled/property/get_property_list_request.py +++ b/src/adcp/types/generated_poc/bundled/property/get_property_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/property/get_property_list_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/property/get_property_list_response.py b/src/adcp/types/generated_poc/bundled/property/get_property_list_response.py index d53d544b6..5ec4d7411 100644 --- a/src/adcp/types/generated_poc/bundled/property/get_property_list_response.py +++ b/src/adcp/types/generated_poc/bundled/property/get_property_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/property/get_property_list_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -125,7 +125,7 @@ class BaseProperties(AdCPBaseModel): selection_type: Annotated[ Literal["publisher_tags"], Field(description="Discriminator indicating selection by property tags within a publisher"), - ] + ] = "publisher_tags" publisher_domain: Annotated[ str, Field( @@ -163,7 +163,7 @@ class BaseProperties10(AdCPBaseModel): Field( description="Discriminator indicating selection by specific property IDs within a publisher" ), - ] + ] = "publisher_ids" publisher_domain: Annotated[ str, Field( @@ -235,7 +235,7 @@ class BaseProperties11(AdCPBaseModel): selection_type: Annotated[ Literal["identifiers"], Field(description="Discriminator indicating selection by direct identifiers"), - ] + ] = "identifiers" identifiers: Annotated[ list[Identifier], Field(description="Direct property identifiers (domains, app IDs, etc.)", min_length=1), @@ -423,7 +423,7 @@ class PricingOption131(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["cpm"] + model: Literal["cpm"] = "cpm" cpm: Annotated[float, Field(description="Cost per thousand impressions", ge=0.0)] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] ext: Annotated[ @@ -439,7 +439,7 @@ class PricingOption132(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["percent_of_media"] + model: Literal["percent_of_media"] = "percent_of_media" percent: Annotated[ float, Field(description="Percentage of media spend, e.g. 15 = 15%", ge=0.0, le=100.0) ] @@ -474,7 +474,7 @@ class PricingOption133(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["flat_fee"] + model: Literal["flat_fee"] = "flat_fee" amount: Annotated[float, Field(description="Fixed charge for the billing period", ge=0.0)] period: Annotated[Period, Field(description="Billing period for the flat fee.")] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] @@ -491,7 +491,7 @@ class PricingOption134(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["per_unit"] + model: Literal["per_unit"] = "per_unit" unit: Annotated[ str, Field( @@ -526,7 +526,7 @@ class PricingOption135(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["custom"] + model: Literal["custom"] = "custom" description: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/bundled/property/list_property_lists_request.py b/src/adcp/types/generated_poc/bundled/property/list_property_lists_request.py index e21a8373b..6dc13d7be 100644 --- a/src/adcp/types/generated_poc/bundled/property/list_property_lists_request.py +++ b/src/adcp/types/generated_poc/bundled/property/list_property_lists_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/property/list_property_lists_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/property/list_property_lists_response.py b/src/adcp/types/generated_poc/bundled/property/list_property_lists_response.py index 861cd749c..615bda739 100644 --- a/src/adcp/types/generated_poc/bundled/property/list_property_lists_response.py +++ b/src/adcp/types/generated_poc/bundled/property/list_property_lists_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/property/list_property_lists_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -125,7 +125,7 @@ class BaseProperties(AdCPBaseModel): selection_type: Annotated[ Literal["publisher_tags"], Field(description="Discriminator indicating selection by property tags within a publisher"), - ] + ] = "publisher_tags" publisher_domain: Annotated[ str, Field( @@ -163,7 +163,7 @@ class BaseProperties14(AdCPBaseModel): Field( description="Discriminator indicating selection by specific property IDs within a publisher" ), - ] + ] = "publisher_ids" publisher_domain: Annotated[ str, Field( @@ -235,7 +235,7 @@ class BaseProperties15(AdCPBaseModel): selection_type: Annotated[ Literal["identifiers"], Field(description="Discriminator indicating selection by direct identifiers"), - ] + ] = "identifiers" identifiers: Annotated[ list[Identifier], Field(description="Direct property identifiers (domains, app IDs, etc.)", min_length=1), @@ -423,7 +423,7 @@ class PricingOption191(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["cpm"] + model: Literal["cpm"] = "cpm" cpm: Annotated[float, Field(description="Cost per thousand impressions", ge=0.0)] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] ext: Annotated[ @@ -439,7 +439,7 @@ class PricingOption192(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["percent_of_media"] + model: Literal["percent_of_media"] = "percent_of_media" percent: Annotated[ float, Field(description="Percentage of media spend, e.g. 15 = 15%", ge=0.0, le=100.0) ] @@ -474,7 +474,7 @@ class PricingOption193(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["flat_fee"] + model: Literal["flat_fee"] = "flat_fee" amount: Annotated[float, Field(description="Fixed charge for the billing period", ge=0.0)] period: Annotated[Period, Field(description="Billing period for the flat fee.")] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] @@ -491,7 +491,7 @@ class PricingOption194(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["per_unit"] + model: Literal["per_unit"] = "per_unit" unit: Annotated[ str, Field( @@ -526,7 +526,7 @@ class PricingOption195(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["custom"] + model: Literal["custom"] = "custom" description: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/bundled/property/update_property_list_request.py b/src/adcp/types/generated_poc/bundled/property/update_property_list_request.py index 36854ac40..5ff21ad60 100644 --- a/src/adcp/types/generated_poc/bundled/property/update_property_list_request.py +++ b/src/adcp/types/generated_poc/bundled/property/update_property_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/property/update_property_list_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -125,7 +125,7 @@ class BaseProperties(AdCPBaseModel): selection_type: Annotated[ Literal["publisher_tags"], Field(description="Discriminator indicating selection by property tags within a publisher"), - ] + ] = "publisher_tags" publisher_domain: Annotated[ str, Field( @@ -163,7 +163,7 @@ class BaseProperties18(AdCPBaseModel): Field( description="Discriminator indicating selection by specific property IDs within a publisher" ), - ] + ] = "publisher_ids" publisher_domain: Annotated[ str, Field( @@ -235,7 +235,7 @@ class BaseProperties19(AdCPBaseModel): selection_type: Annotated[ Literal["identifiers"], Field(description="Discriminator indicating selection by direct identifiers"), - ] + ] = "identifiers" identifiers: Annotated[ list[Identifier], Field(description="Direct property identifiers (domains, app IDs, etc.)", min_length=1), diff --git a/src/adcp/types/generated_poc/bundled/property/update_property_list_response.py b/src/adcp/types/generated_poc/bundled/property/update_property_list_response.py index 75aedf991..f8ca86f0b 100644 --- a/src/adcp/types/generated_poc/bundled/property/update_property_list_response.py +++ b/src/adcp/types/generated_poc/bundled/property/update_property_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/property/update_property_list_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -125,7 +125,7 @@ class BaseProperties(AdCPBaseModel): selection_type: Annotated[ Literal["publisher_tags"], Field(description="Discriminator indicating selection by property tags within a publisher"), - ] + ] = "publisher_tags" publisher_domain: Annotated[ str, Field( @@ -163,7 +163,7 @@ class BaseProperties22(AdCPBaseModel): Field( description="Discriminator indicating selection by specific property IDs within a publisher" ), - ] + ] = "publisher_ids" publisher_domain: Annotated[ str, Field( @@ -235,7 +235,7 @@ class BaseProperties23(AdCPBaseModel): selection_type: Annotated[ Literal["identifiers"], Field(description="Discriminator indicating selection by direct identifiers"), - ] + ] = "identifiers" identifiers: Annotated[ list[Identifier], Field(description="Direct property identifiers (domains, app IDs, etc.)", min_length=1), @@ -423,7 +423,7 @@ class PricingOption201(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["cpm"] + model: Literal["cpm"] = "cpm" cpm: Annotated[float, Field(description="Cost per thousand impressions", ge=0.0)] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] ext: Annotated[ @@ -439,7 +439,7 @@ class PricingOption202(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["percent_of_media"] + model: Literal["percent_of_media"] = "percent_of_media" percent: Annotated[ float, Field(description="Percentage of media spend, e.g. 15 = 15%", ge=0.0, le=100.0) ] @@ -474,7 +474,7 @@ class PricingOption203(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["flat_fee"] + model: Literal["flat_fee"] = "flat_fee" amount: Annotated[float, Field(description="Fixed charge for the billing period", ge=0.0)] period: Annotated[Period, Field(description="Billing period for the flat fee.")] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] @@ -491,7 +491,7 @@ class PricingOption204(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["per_unit"] + model: Literal["per_unit"] = "per_unit" unit: Annotated[ str, Field( @@ -526,7 +526,7 @@ class PricingOption205(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["custom"] + model: Literal["custom"] = "custom" description: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/bundled/property/validate_property_delivery_request.py b/src/adcp/types/generated_poc/bundled/property/validate_property_delivery_request.py index 0434893b7..2f37886d1 100644 --- a/src/adcp/types/generated_poc/bundled/property/validate_property_delivery_request.py +++ b/src/adcp/types/generated_poc/bundled/property/validate_property_delivery_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/property/validate_property_delivery_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/property/validate_property_delivery_response.py b/src/adcp/types/generated_poc/bundled/property/validate_property_delivery_response.py index f01aa6f05..4e29aecb4 100644 --- a/src/adcp/types/generated_poc/bundled/property/validate_property_delivery_response.py +++ b/src/adcp/types/generated_poc/bundled/property/validate_property_delivery_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/property/validate_property_delivery_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -152,7 +152,7 @@ class Status(Enum): unidentified = "unidentified" -class Status49(Enum): +class Status53(Enum): passed = "passed" failed = "failed" warning = "warning" @@ -180,7 +180,7 @@ class Feature(AdCPBaseModel): description="Which feature was evaluated. Data features come from the governance agent's feature catalog (e.g., 'mfa_score', 'carbon_score'). Record-level structural checks use reserved namespaces: 'record:list_membership', 'record:excluded', 'delivery:seller_authorization', 'delivery:click_url_presence'. Reserved prefixes: 'record:', 'delivery:'." ), ] - status: Status49 + status: Status53 policy_id: Annotated[ str | None, Field( @@ -206,7 +206,7 @@ class Feature(AdCPBaseModel): ] = None -class Status50(Enum): +class Status54(Enum): authorized = "authorized" unauthorized = "unauthorized" unknown = "unknown" @@ -225,7 +225,7 @@ class Authorization(AdCPBaseModel): extra="forbid", ) status: Annotated[ - Status50, + Status54, Field( description="Authorization status: authorized (agent in adagents.json), unauthorized (agent not in adagents.json), unknown (could not fetch or parse adagents.json)" ), diff --git a/src/adcp/types/generated_poc/bundled/protocol/get_adcp_capabilities_request.py b/src/adcp/types/generated_poc/bundled/protocol/get_adcp_capabilities_request.py index 7cd8f2b67..f5c2e472b 100644 --- a/src/adcp/types/generated_poc/bundled/protocol/get_adcp_capabilities_request.py +++ b/src/adcp/types/generated_poc/bundled/protocol/get_adcp_capabilities_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/protocol/get_adcp_capabilities_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/protocol/get_adcp_capabilities_response.py b/src/adcp/types/generated_poc/bundled/protocol/get_adcp_capabilities_response.py index 13f115067..05169d62b 100644 --- a/src/adcp/types/generated_poc/bundled/protocol/get_adcp_capabilities_response.py +++ b/src/adcp/types/generated_poc/bundled/protocol/get_adcp_capabilities_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/protocol/get_adcp_capabilities_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/signals/activate_signal_request.py b/src/adcp/types/generated_poc/bundled/signals/activate_signal_request.py index c1ca483a1..eeb53787a 100644 --- a/src/adcp/types/generated_poc/bundled/signals/activate_signal_request.py +++ b/src/adcp/types/generated_poc/bundled/signals/activate_signal_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/signals/activate_signal_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -23,7 +23,7 @@ class Destinations(AdCPBaseModel): type: Annotated[ Literal["platform"], Field(description="Discriminator indicating this is a platform-based deployment"), - ] + ] = "platform" platform: Annotated[ str, Field(description="Platform identifier for DSPs (e.g., 'the-trade-desk', 'amazon-dsp')"), @@ -40,7 +40,7 @@ class Destinations1(AdCPBaseModel): type: Annotated[ Literal["agent"], Field(description="Discriminator indicating this is an agent URL-based deployment"), - ] + ] = "agent" agent_url: Annotated[ AnyUrl, Field(description="URL identifying the deployment agent (for sales agents, etc.)") ] diff --git a/src/adcp/types/generated_poc/bundled/signals/activate_signal_response.py b/src/adcp/types/generated_poc/bundled/signals/activate_signal_response.py index a780da99c..87ad2df26 100644 --- a/src/adcp/types/generated_poc/bundled/signals/activate_signal_response.py +++ b/src/adcp/types/generated_poc/bundled/signals/activate_signal_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/signals/activate_signal_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -15,7 +15,9 @@ class ActivationKey(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - type: Annotated[Literal["segment_id"], Field(description="Segment ID based targeting")] + type: Annotated[Literal["segment_id"], Field(description="Segment ID based targeting")] = ( + "segment_id" + ) segment_id: Annotated[ str, Field(description="The platform-specific segment identifier to use in campaign targeting"), @@ -26,7 +28,9 @@ class ActivationKey1(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - type: Annotated[Literal["key_value"], Field(description="Key-value pair based targeting")] + type: Annotated[Literal["key_value"], Field(description="Key-value pair based targeting")] = ( + "key_value" + ) key: Annotated[str, Field(description="The targeting parameter key")] value: Annotated[str, Field(description="The targeting parameter value")] @@ -38,7 +42,7 @@ class Deployments(AdCPBaseModel): type: Annotated[ Literal["platform"], Field(description="Discriminator indicating this is a platform-based deployment"), - ] + ] = "platform" platform: Annotated[str, Field(description="Platform identifier for DSPs")] account: Annotated[str | None, Field(description="Account identifier if applicable")] = None is_live: Annotated[ @@ -79,7 +83,7 @@ class Deployments1(AdCPBaseModel): type: Annotated[ Literal["agent"], Field(description="Discriminator indicating this is an agent URL-based deployment"), - ] + ] = "agent" agent_url: Annotated[AnyUrl, Field(description="URL identifying the deployment agent")] account: Annotated[str | None, Field(description="Account identifier if applicable")] = None is_live: Annotated[ diff --git a/src/adcp/types/generated_poc/bundled/signals/get_signals_request.py b/src/adcp/types/generated_poc/bundled/signals/get_signals_request.py index 0ee5187d6..944d6271a 100644 --- a/src/adcp/types/generated_poc/bundled/signals/get_signals_request.py +++ b/src/adcp/types/generated_poc/bundled/signals/get_signals_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/signals/get_signals_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -115,7 +115,7 @@ class SignalIds1(AdCPBaseModel): Field( description="Discriminator indicating this signal is from a data provider's published catalog" ), - ] + ] = "catalog" data_provider_domain: Annotated[ str, Field( @@ -141,7 +141,7 @@ class SignalIds2(AdCPBaseModel): Field( description="Discriminator indicating this signal is native to the agent (not from a data provider catalog)" ), - ] + ] = "agent" agent_url: Annotated[ AnyUrl, Field( @@ -181,7 +181,7 @@ class Destinations(AdCPBaseModel): type: Annotated[ Literal["platform"], Field(description="Discriminator indicating this is a platform-based deployment"), - ] + ] = "platform" platform: Annotated[ str, Field(description="Platform identifier for DSPs (e.g., 'the-trade-desk', 'amazon-dsp')"), @@ -198,7 +198,7 @@ class Destinations3(AdCPBaseModel): type: Annotated[ Literal["agent"], Field(description="Discriminator indicating this is an agent URL-based deployment"), - ] + ] = "agent" agent_url: Annotated[ AnyUrl, Field(description="URL identifying the deployment agent (for sales agents, etc.)") ] diff --git a/src/adcp/types/generated_poc/bundled/signals/get_signals_response.py b/src/adcp/types/generated_poc/bundled/signals/get_signals_response.py index 09cb9a4ba..7592506ab 100644 --- a/src/adcp/types/generated_poc/bundled/signals/get_signals_response.py +++ b/src/adcp/types/generated_poc/bundled/signals/get_signals_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/signals/get_signals_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -20,7 +20,7 @@ class SignalId(AdCPBaseModel): Field( description="Discriminator indicating this signal is from a data provider's published catalog" ), - ] + ] = "catalog" data_provider_domain: Annotated[ str, Field( @@ -46,7 +46,7 @@ class SignalId16(AdCPBaseModel): Field( description="Discriminator indicating this signal is native to the agent (not from a data provider catalog)" ), - ] + ] = "agent" agent_url: Annotated[ AnyUrl, Field( @@ -86,7 +86,9 @@ class ActivationKey(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - type: Annotated[Literal["segment_id"], Field(description="Segment ID based targeting")] + type: Annotated[Literal["segment_id"], Field(description="Segment ID based targeting")] = ( + "segment_id" + ) segment_id: Annotated[ str, Field(description="The platform-specific segment identifier to use in campaign targeting"), @@ -97,7 +99,9 @@ class ActivationKey7(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - type: Annotated[Literal["key_value"], Field(description="Key-value pair based targeting")] + type: Annotated[Literal["key_value"], Field(description="Key-value pair based targeting")] = ( + "key_value" + ) key: Annotated[str, Field(description="The targeting parameter key")] value: Annotated[str, Field(description="The targeting parameter value")] @@ -109,7 +113,7 @@ class Deployments(AdCPBaseModel): type: Annotated[ Literal["platform"], Field(description="Discriminator indicating this is a platform-based deployment"), - ] + ] = "platform" platform: Annotated[str, Field(description="Platform identifier for DSPs")] account: Annotated[str | None, Field(description="Account identifier if applicable")] = None is_live: Annotated[ @@ -150,7 +154,7 @@ class Deployments3(AdCPBaseModel): type: Annotated[ Literal["agent"], Field(description="Discriminator indicating this is an agent URL-based deployment"), - ] + ] = "agent" agent_url: Annotated[AnyUrl, Field(description="URL identifying the deployment agent")] account: Annotated[str | None, Field(description="Account identifier if applicable")] = None is_live: Annotated[ @@ -180,7 +184,7 @@ class PricingOption141(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["cpm"] + model: Literal["cpm"] = "cpm" cpm: Annotated[float, Field(description="Cost per thousand impressions", ge=0.0)] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] ext: Annotated[ @@ -196,7 +200,7 @@ class PricingOption142(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["percent_of_media"] + model: Literal["percent_of_media"] = "percent_of_media" percent: Annotated[ float, Field(description="Percentage of media spend, e.g. 15 = 15%", ge=0.0, le=100.0) ] @@ -231,7 +235,7 @@ class PricingOption143(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["flat_fee"] + model: Literal["flat_fee"] = "flat_fee" amount: Annotated[float, Field(description="Fixed charge for the billing period", ge=0.0)] period: Annotated[Period, Field(description="Billing period for the flat fee.")] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] @@ -248,7 +252,7 @@ class PricingOption144(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["per_unit"] + model: Literal["per_unit"] = "per_unit" unit: Annotated[ str, Field( @@ -283,7 +287,7 @@ class PricingOption145(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["custom"] + model: Literal["custom"] = "custom" description: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_get_offering_request.py b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_get_offering_request.py index ba10234b1..1a540b0b2 100644 --- a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_get_offering_request.py +++ b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_get_offering_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/sponsored_intelligence/si_get_offering_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -25,10 +25,17 @@ class SiGetOfferingRequest(AdCPBaseModel): offering_id: Annotated[ str, Field(description="Offering identifier from the catalog to get details for") ] - context: Annotated[ + intent: 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." + description="Optional natural language description of user intent for personalized results (e.g., 'mens size 14 near Cincinnati'). Must be anonymous - no PII." + ), + ] = None + context: Annotated[ + dict[str, Any] | None, + Field( + description="Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + title="Context Object", ), ] = None include_products: Annotated[ diff --git a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_get_offering_response.py b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_get_offering_response.py index e7ceeab7a..cc9f74320 100644 --- a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_get_offering_response.py +++ b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_get_offering_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/sponsored_intelligence/si_get_offering_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_initiate_session_request.py b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_initiate_session_request.py index 190dcfaed..103cc640d 100644 --- a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_initiate_session_request.py +++ b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_initiate_session_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/sponsored_intelligence/si_initiate_session_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -196,9 +196,19 @@ class SiInitiateSessionRequest(AdCPBaseModel): le=99, ), ] = None - context: Annotated[ - str, Field(description="Conversation handoff from the host describing what the user needs") + intent: Annotated[ + str, + Field( + description="Natural language description of user intent — the conversation handoff from the host describing what the user needs from the brand agent" + ), ] + context: Annotated[ + dict[str, Any] | None, + Field( + description="Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + title="Context Object", + ), + ] = None identity: Annotated[ Identity, Field( diff --git a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_initiate_session_response.py b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_initiate_session_response.py index b14a6a3c9..8e384ceba 100644 --- a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_initiate_session_response.py +++ b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_initiate_session_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/sponsored_intelligence/si_initiate_session_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_send_message_request.py b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_send_message_request.py index d02b6a84c..b608c90f0 100644 --- a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_send_message_request.py +++ b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_send_message_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/sponsored_intelligence/si_send_message_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_send_message_response.py b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_send_message_response.py index c6bd8157a..b9395aa3c 100644 --- a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_send_message_response.py +++ b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_send_message_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/sponsored_intelligence/si_send_message_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_terminate_session_request.py b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_terminate_session_request.py index 8ac5a12da..ffb52a0eb 100644 --- a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_terminate_session_request.py +++ b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_terminate_session_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/sponsored_intelligence/si_terminate_session_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_terminate_session_response.py b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_terminate_session_response.py index 252e0ec9d..8b4616efd 100644 --- a/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_terminate_session_response.py +++ b/src/adcp/types/generated_poc/bundled/sponsored_intelligence/si_terminate_session_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: bundled/sponsored_intelligence/si_terminate_session_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/collection/base_collection_source.py b/src/adcp/types/generated_poc/collection/base_collection_source.py index c547d7c57..25c8b2985 100644 --- a/src/adcp/types/generated_poc/collection/base_collection_source.py +++ b/src/adcp/types/generated_poc/collection/base_collection_source.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/base_collection_source.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -22,7 +22,7 @@ class BaseCollectionSource2(AdCPBaseModel): Field( description="Discriminator indicating selection by specific collection IDs within a publisher" ), - ] + ] = "publisher_collections" publisher_domain: Annotated[ str, Field( @@ -58,7 +58,7 @@ class BaseCollectionSource1(AdCPBaseModel): Field( description="Discriminator indicating selection by platform-independent distribution identifiers" ), - ] + ] = "distribution_ids" identifiers: Annotated[ list[Identifier], Field( @@ -75,7 +75,7 @@ class BaseCollectionSource3(AdCPBaseModel): selection_type: Annotated[ Literal["publisher_genres"], Field(description="Discriminator indicating selection by genre within a publisher"), - ] + ] = "publisher_genres" publisher_domain: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/collection/collection_list.py b/src/adcp/types/generated_poc/collection/collection_list.py index eea68c3d5..9a527f262 100644 --- a/src/adcp/types/generated_poc/collection/collection_list.py +++ b/src/adcp/types/generated_poc/collection/collection_list.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/collection_list.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/collection/collection_list_changed_webhook.py b/src/adcp/types/generated_poc/collection/collection_list_changed_webhook.py index 56c67ef87..59c625dca 100644 --- a/src/adcp/types/generated_poc/collection/collection_list_changed_webhook.py +++ b/src/adcp/types/generated_poc/collection/collection_list_changed_webhook.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/collection_list_changed_webhook.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -40,7 +40,9 @@ class CollectionListChangedWebhook(AdCPBaseModel): pattern="^[A-Za-z0-9_.:-]{16,255}$", ), ] - event: Annotated[Literal["collection_list_changed"], Field(description="The event type")] + event: Annotated[Literal["collection_list_changed"], Field(description="The event type")] = ( + "collection_list_changed" + ) list_id: Annotated[str, Field(description="ID of the collection list that changed")] list_name: Annotated[str | None, Field(description="Name of the collection list")] = None change_summary: Annotated[ diff --git a/src/adcp/types/generated_poc/collection/collection_list_filters.py b/src/adcp/types/generated_poc/collection/collection_list_filters.py index 31e7ea093..6610a0928 100644 --- a/src/adcp/types/generated_poc/collection/collection_list_filters.py +++ b/src/adcp/types/generated_poc/collection/collection_list_filters.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/collection_list_filters.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/collection/create_collection_list_request.py b/src/adcp/types/generated_poc/collection/create_collection_list_request.py index a52c37224..80663f492 100644 --- a/src/adcp/types/generated_poc/collection/create_collection_list_request.py +++ b/src/adcp/types/generated_poc/collection/create_collection_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/create_collection_list_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/collection/create_collection_list_response.py b/src/adcp/types/generated_poc/collection/create_collection_list_response.py index 065583594..22cf031c5 100644 --- a/src/adcp/types/generated_poc/collection/create_collection_list_response.py +++ b/src/adcp/types/generated_poc/collection/create_collection_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/create_collection_list_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/collection/delete_collection_list_request.py b/src/adcp/types/generated_poc/collection/delete_collection_list_request.py index d3cdfaf7e..91a3fac88 100644 --- a/src/adcp/types/generated_poc/collection/delete_collection_list_request.py +++ b/src/adcp/types/generated_poc/collection/delete_collection_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/delete_collection_list_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/collection/delete_collection_list_response.py b/src/adcp/types/generated_poc/collection/delete_collection_list_response.py index b109eda54..f263ef33a 100644 --- a/src/adcp/types/generated_poc/collection/delete_collection_list_response.py +++ b/src/adcp/types/generated_poc/collection/delete_collection_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/delete_collection_list_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/collection/get_collection_list_request.py b/src/adcp/types/generated_poc/collection/get_collection_list_request.py index d1588b095..e947287f7 100644 --- a/src/adcp/types/generated_poc/collection/get_collection_list_request.py +++ b/src/adcp/types/generated_poc/collection/get_collection_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/get_collection_list_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/collection/get_collection_list_response.py b/src/adcp/types/generated_poc/collection/get_collection_list_response.py index 2887e8d95..a50bd6053 100644 --- a/src/adcp/types/generated_poc/collection/get_collection_list_response.py +++ b/src/adcp/types/generated_poc/collection/get_collection_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/get_collection_list_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/collection/list_collection_lists_request.py b/src/adcp/types/generated_poc/collection/list_collection_lists_request.py index 247b4ca0c..4b042a8d7 100644 --- a/src/adcp/types/generated_poc/collection/list_collection_lists_request.py +++ b/src/adcp/types/generated_poc/collection/list_collection_lists_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/list_collection_lists_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/collection/list_collection_lists_response.py b/src/adcp/types/generated_poc/collection/list_collection_lists_response.py index 158fdd1d6..576d23ad0 100644 --- a/src/adcp/types/generated_poc/collection/list_collection_lists_response.py +++ b/src/adcp/types/generated_poc/collection/list_collection_lists_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/list_collection_lists_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/collection/update_collection_list_request.py b/src/adcp/types/generated_poc/collection/update_collection_list_request.py index 41771da69..5a3bfa423 100644 --- a/src/adcp/types/generated_poc/collection/update_collection_list_request.py +++ b/src/adcp/types/generated_poc/collection/update_collection_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/update_collection_list_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/collection/update_collection_list_response.py b/src/adcp/types/generated_poc/collection/update_collection_list_response.py index 9586bd7c7..c1e843330 100644 --- a/src/adcp/types/generated_poc/collection/update_collection_list_response.py +++ b/src/adcp/types/generated_poc/collection/update_collection_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: collection/update_collection_list_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/compliance/comply_test_controller_request.py b/src/adcp/types/generated_poc/compliance/comply_test_controller_request.py index 44dbbf8c2..633f5a65e 100644 --- a/src/adcp/types/generated_poc/compliance/comply_test_controller_request.py +++ b/src/adcp/types/generated_poc/compliance/comply_test_controller_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: compliance/comply_test_controller_request.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/compliance/comply_test_controller_response.py b/src/adcp/types/generated_poc/compliance/comply_test_controller_response.py index 39674016b..498b37da2 100644 --- a/src/adcp/types/generated_poc/compliance/comply_test_controller_response.py +++ b/src/adcp/types/generated_poc/compliance/comply_test_controller_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: compliance/comply_test_controller_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/content_standards/artifact.py b/src/adcp/types/generated_poc/content_standards/artifact.py index 91f5f497f..239b5708c 100644 --- a/src/adcp/types/generated_poc/content_standards/artifact.py +++ b/src/adcp/types/generated_poc/content_standards/artifact.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/artifact.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -81,7 +81,7 @@ class Identifiers(AdCPBaseModel): class AssetAccess1(AdCPBaseModel): - method: Literal["bearer_token"] + method: Literal["bearer_token"] = "bearer_token" token: Annotated[str, Field(description="OAuth2 bearer token for Authorization header")] @@ -91,7 +91,7 @@ class Provider(Enum): class AssetAccess2(AdCPBaseModel): - method: Literal["service_account"] + method: Literal["service_account"] = "service_account" provider: Annotated[Provider, Field(description="Cloud provider")] credentials: Annotated[ dict[str, Any] | None, Field(description="Service account credentials") @@ -99,7 +99,7 @@ class AssetAccess2(AdCPBaseModel): class AssetAccess3(AdCPBaseModel): - method: Literal["signed_url"] + method: Literal["signed_url"] = "signed_url" class AssetAccess(RootModel[AssetAccess1 | AssetAccess2 | AssetAccess3]): @@ -116,7 +116,7 @@ def __getattr__(self, name: str) -> Any: class Assets(AdCPBaseModel): - type: Literal["text"] + type: Literal["text"] = "text" role: Annotated[ Role | None, Field( @@ -152,7 +152,7 @@ class Assets(AdCPBaseModel): class Assets1(AdCPBaseModel): - type: Literal["image"] + type: Literal["image"] = "image" url: Annotated[AnyUrl, Field(description="Image URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -168,7 +168,7 @@ class Assets1(AdCPBaseModel): class Assets2(AdCPBaseModel): - type: Literal["video"] + type: Literal["video"] = "video" url: Annotated[AnyUrl, Field(description="Video URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( None @@ -198,7 +198,7 @@ class Assets2(AdCPBaseModel): class Assets3(AdCPBaseModel): - type: Literal["audio"] + type: Literal["audio"] = "audio" url: Annotated[AnyUrl, Field(description="Audio URL")] access: Annotated[AssetAccess | None, Field(description="Authentication for secured URLs")] = ( 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 index ed46a231c..581e999c9 100644 --- a/src/adcp/types/generated_poc/content_standards/artifact_webhook_payload.py +++ b/src/adcp/types/generated_poc/content_standards/artifact_webhook_payload.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/artifact_webhook_payload.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 99dfe678a..b35ef4ecb 100644 --- a/src/adcp/types/generated_poc/content_standards/calibrate_content_request.py +++ b/src/adcp/types/generated_poc/content_standards/calibrate_content_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/calibrate_content_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 6d26d2583..8db3000ba 100644 --- a/src/adcp/types/generated_poc/content_standards/calibrate_content_response.py +++ b/src/adcp/types/generated_poc/content_standards/calibrate_content_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/calibrate_content_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/content_standards/content_standards.py b/src/adcp/types/generated_poc/content_standards/content_standards.py index 8a67d0b69..372c28dc0 100644 --- a/src/adcp/types/generated_poc/content_standards/content_standards.py +++ b/src/adcp/types/generated_poc/content_standards/content_standards.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/content_standards.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 6441052a1..e3486ade3 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/create_content_standards_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -44,7 +44,7 @@ class Scope(AdCPBaseModel): class Pass(AdCPBaseModel): - type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] + type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] = "url" value: Annotated[ AnyUrl, Field( @@ -57,7 +57,7 @@ class Pass(AdCPBaseModel): class Fail(AdCPBaseModel): - type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] + type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] = "url" value: Annotated[ AnyUrl, Field( 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 index 42abe5222..72b5cc172 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/create_content_standards_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 21acec9d9..c8c693928 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/get_content_standards_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index d40301579..b4d62e7fa 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/get_media_buy_artifacts_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 596302462..b242e875c 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/get_media_buy_artifacts_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 95f584e85..be6aaf079 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/list_content_standards_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 3b56e2800..6e07c933a 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/list_content_standards_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 851ddba61..ada3fb357 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/update_content_standards_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -44,7 +44,7 @@ class Scope(AdCPBaseModel): class Pass(AdCPBaseModel): - type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] + type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] = "url" value: Annotated[ AnyUrl, Field( @@ -57,7 +57,7 @@ class Pass(AdCPBaseModel): class Fail(AdCPBaseModel): - type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] + type: Annotated[Literal["url"], Field(description="Indicates this is a URL reference")] = "url" value: Annotated[ AnyUrl, Field( 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 0bd1fbfcb..015b96902 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 7fdc9e8a5..f2d9cbb34 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/validate_content_delivery_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 0d212156f..aa757462c 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: content_standards/validate_content_delivery_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/account.py b/src/adcp/types/generated_poc/core/account.py index d14f70016..b6b4aabef 100644 --- a/src/adcp/types/generated_poc/core/account.py +++ b/src/adcp/types/generated_poc/core/account.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/account.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/account_ref.py b/src/adcp/types/generated_poc/core/account_ref.py index 9664fcf02..dc6b35f13 100644 --- a/src/adcp/types/generated_poc/core/account_ref.py +++ b/src/adcp/types/generated_poc/core/account_ref.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/account_ref.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/activation_key.py b/src/adcp/types/generated_poc/core/activation_key.py index fffda7493..ca24c30c3 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -14,7 +14,9 @@ class ActivationKey4(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - type: Annotated[Literal["segment_id"], Field(description="Segment ID based targeting")] + type: Annotated[Literal["segment_id"], Field(description="Segment ID based targeting")] = ( + "segment_id" + ) segment_id: Annotated[ str, Field(description="The platform-specific segment identifier to use in campaign targeting"), @@ -25,7 +27,9 @@ class ActivationKey5(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - type: Annotated[Literal["key_value"], Field(description="Key-value pair based targeting")] + type: Annotated[Literal["key_value"], Field(description="Key-value pair based targeting")] = ( + "key_value" + ) key: Annotated[str, Field(description="The targeting parameter key")] value: Annotated[str, Field(description="The targeting parameter value")] diff --git a/src/adcp/types/generated_poc/core/ad_inventory_config.py b/src/adcp/types/generated_poc/core/ad_inventory_config.py index 26d17d458..c63a9dab5 100644 --- a/src/adcp/types/generated_poc/core/ad_inventory_config.py +++ b/src/adcp/types/generated_poc/core/ad_inventory_config.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/ad_inventory_config.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/agent_encryption_key.py b/src/adcp/types/generated_poc/core/agent_encryption_key.py index edf2e3060..d6f41dac3 100644 --- a/src/adcp/types/generated_poc/core/agent_encryption_key.py +++ b/src/adcp/types/generated_poc/core/agent_encryption_key.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/agent_encryption_key.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -21,11 +21,13 @@ class AgentEncryptionKey(AdCPBaseModel): max_length=8, ), ] - kty: Annotated[Literal["OKP"], Field(description="JWK key type. Must be OKP for X25519.")] + kty: Annotated[Literal["OKP"], Field(description="JWK key type. Must be OKP for X25519.")] = ( + "OKP" + ) crv: Annotated[ Literal["X25519"], Field(description="Curve name. Must be X25519 for TMPX encryption.") - ] + ] = "X25519" use: Annotated[ Literal["enc"], Field(description="JWK use value. Must be enc for encryption keys.") - ] + ] = "enc" x: Annotated[str, Field(description="Base64url-encoded X25519 public key (32 bytes).")] diff --git a/src/adcp/types/generated_poc/core/agent_signing_key.py b/src/adcp/types/generated_poc/core/agent_signing_key.py index a410a2b17..a7507c468 100644 --- a/src/adcp/types/generated_poc/core/agent_signing_key.py +++ b/src/adcp/types/generated_poc/core/agent_signing_key.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/agent_signing_key.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/app_item.py b/src/adcp/types/generated_poc/core/app_item.py index 077718092..ddd91d9e9 100644 --- a/src/adcp/types/generated_poc/core/app_item.py +++ b/src/adcp/types/generated_poc/core/app_item.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/app_item.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 3bfbc6366..cd74e12dd 100644 --- a/src/adcp/types/generated_poc/core/assets/audio_asset.py +++ b/src/adcp/types/generated_poc/core/assets/audio_asset.py @@ -1,11 +1,11 @@ # generated by datamodel-codegen: # filename: core/assets/audio_asset.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations from enum import Enum, IntEnum -from typing import Annotated +from typing import Annotated, Literal from adcp.types.base import AdCPBaseModel from pydantic import AnyUrl, ConfigDict, Field @@ -30,6 +30,12 @@ class AudioAsset(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["audio"], + Field( + description="Discriminator identifying this as an audio asset. See /schemas/creative/asset-types for the registry." + ), + ] = "audio" url: Annotated[AnyUrl, Field(description="URL to the audio asset")] duration_ms: Annotated[ int | None, Field(description="Audio duration in milliseconds", ge=0) diff --git a/src/adcp/types/generated_poc/core/assets/brief_asset.py b/src/adcp/types/generated_poc/core/assets/brief_asset.py index 100139769..5e3dbfb24 100644 --- a/src/adcp/types/generated_poc/core/assets/brief_asset.py +++ b/src/adcp/types/generated_poc/core/assets/brief_asset.py @@ -1,11 +1,20 @@ # generated by datamodel-codegen: # filename: core/assets/brief_asset.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations +from typing import Annotated, Literal + +from pydantic import Field + from ..creative_brief import CreativeBrief class BriefAsset(CreativeBrief): - pass + asset_type: Annotated[ + Literal["brief"], + Field( + description="Discriminator identifying this as a brief asset. See /schemas/creative/asset-types for the registry." + ), + ] = "brief" diff --git a/src/adcp/types/generated_poc/core/assets/catalog_asset.py b/src/adcp/types/generated_poc/core/assets/catalog_asset.py index 274aee8fb..dd67c7ab5 100644 --- a/src/adcp/types/generated_poc/core/assets/catalog_asset.py +++ b/src/adcp/types/generated_poc/core/assets/catalog_asset.py @@ -1,11 +1,20 @@ # generated by datamodel-codegen: # filename: core/assets/catalog_asset.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations +from typing import Annotated, Literal + +from pydantic import Field + from ..catalog import Catalog class CatalogAsset(Catalog): - pass + asset_type: Annotated[ + Literal["catalog"], + Field( + description="Discriminator identifying this as a catalog asset. See /schemas/creative/asset-types for the registry." + ), + ] = "catalog" 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 6e7aa78aa..83ee8d139 100644 --- a/src/adcp/types/generated_poc/core/assets/css_asset.py +++ b/src/adcp/types/generated_poc/core/assets/css_asset.py @@ -1,10 +1,10 @@ # generated by datamodel-codegen: # filename: core/assets/css_asset.json -# timestamp: 2026-02-28T17:39:50+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations -from typing import Annotated +from typing import Annotated, Literal from adcp.types.base import AdCPBaseModel from pydantic import ConfigDict, Field @@ -16,6 +16,12 @@ class CssAsset(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["css"], + Field( + description="Discriminator identifying this as a CSS asset. See /schemas/creative/asset-types for the registry." + ), + ] = "css" content: Annotated[str, Field(description="CSS content")] media: Annotated[ str | None, Field(description="CSS media query context (e.g., 'screen', 'print')") 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 c4f96569b..8676028bc 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -18,11 +18,12 @@ class DaastAsset1(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ daast_version_1.DaastVersion | None, Field(description="DAAST specification version") ] = None @@ -45,17 +46,23 @@ class DaastAsset1(AdCPBaseModel): description="Provenance metadata for this asset, overrides manifest-level provenance" ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating DAAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns DAAST XML")] class DaastAsset2(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating DAAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline DAAST XML content")] + asset_type: Annotated[ + Literal["daast"], + Field( + description="Discriminator identifying this as a DAAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "daast" daast_version: Annotated[ daast_version_1.DaastVersion | None, Field(description="DAAST specification version") ] = None @@ -78,6 +85,11 @@ class DaastAsset2(AdCPBaseModel): description="Provenance metadata for this asset, overrides manifest-level provenance" ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating DAAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline DAAST XML content")] class DaastAsset(RootModel[DaastAsset1 | DaastAsset2]): @@ -85,6 +97,7 @@ class DaastAsset(RootModel[DaastAsset1 | DaastAsset2]): DaastAsset1 | DaastAsset2, Field( description="DAAST (Digital Audio Ad Serving Template) tag for third-party audio ad serving", + discriminator="delivery_type", 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 d11fdd607..a95d5a5f9 100644 --- a/src/adcp/types/generated_poc/core/assets/html_asset.py +++ b/src/adcp/types/generated_poc/core/assets/html_asset.py @@ -1,10 +1,10 @@ # generated by datamodel-codegen: # filename: core/assets/html_asset.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations -from typing import Annotated +from typing import Annotated, Literal from adcp.types.base import AdCPBaseModel from pydantic import ConfigDict, Field @@ -34,6 +34,12 @@ class HtmlAsset(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["html"], + Field( + description="Discriminator identifying this as an HTML asset. See /schemas/creative/asset-types for the registry." + ), + ] = "html" content: Annotated[str, Field(description="HTML content")] version: Annotated[str | None, Field(description="HTML version (e.g., 'HTML5')")] = None accessibility: Annotated[ 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 dd679f26b..b85b66b58 100644 --- a/src/adcp/types/generated_poc/core/assets/image_asset.py +++ b/src/adcp/types/generated_poc/core/assets/image_asset.py @@ -1,10 +1,10 @@ # generated by datamodel-codegen: # filename: core/assets/image_asset.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations -from typing import Annotated +from typing import Annotated, Literal from adcp.types.base import AdCPBaseModel from pydantic import AnyUrl, ConfigDict, Field @@ -16,6 +16,12 @@ class ImageAsset(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["image"], + Field( + description="Discriminator identifying this as an image asset. See /schemas/creative/asset-types for the registry." + ), + ] = "image" 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)] 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 f46ad936c..8a0f5d42b 100644 --- a/src/adcp/types/generated_poc/core/assets/javascript_asset.py +++ b/src/adcp/types/generated_poc/core/assets/javascript_asset.py @@ -1,10 +1,10 @@ # generated by datamodel-codegen: # filename: core/assets/javascript_asset.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations -from typing import Annotated +from typing import Annotated, Literal from adcp.types.base import AdCPBaseModel from pydantic import ConfigDict, Field @@ -35,6 +35,12 @@ class JavascriptAsset(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["javascript"], + Field( + description="Discriminator identifying this as a JavaScript asset. See /schemas/creative/asset-types for the registry." + ), + ] = "javascript" content: Annotated[str, Field(description="JavaScript content")] module_type: Annotated[ javascript_module_type.JavascriptModuleType | None, diff --git a/src/adcp/types/generated_poc/core/assets/markdown_asset.py b/src/adcp/types/generated_poc/core/assets/markdown_asset.py index 4f0ce09b7..d7ed1d847 100644 --- a/src/adcp/types/generated_poc/core/assets/markdown_asset.py +++ b/src/adcp/types/generated_poc/core/assets/markdown_asset.py @@ -1,10 +1,10 @@ # generated by datamodel-codegen: # filename: core/assets/markdown_asset.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations -from typing import Annotated +from typing import Annotated, Literal from adcp.types.base import AdCPBaseModel from pydantic import ConfigDict, Field @@ -16,6 +16,12 @@ class MarkdownAsset(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["markdown"], + Field( + description="Discriminator identifying this as a markdown asset. See /schemas/creative/asset-types for the registry." + ), + ] = "markdown" content: Annotated[ str, Field( 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 10756f306..0d2eda735 100644 --- a/src/adcp/types/generated_poc/core/assets/text_asset.py +++ b/src/adcp/types/generated_poc/core/assets/text_asset.py @@ -1,10 +1,10 @@ # generated by datamodel-codegen: # filename: core/assets/text_asset.json -# timestamp: 2026-02-28T17:39:50+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations -from typing import Annotated +from typing import Annotated, Literal from adcp.types.base import AdCPBaseModel from pydantic import ConfigDict, Field @@ -16,6 +16,12 @@ class TextAsset(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["text"], + Field( + description="Discriminator identifying this as a text asset. See /schemas/creative/asset-types for the registry." + ), + ] = "text" 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 e09899c0f..8ef0be778 100644 --- a/src/adcp/types/generated_poc/core/assets/url_asset.py +++ b/src/adcp/types/generated_poc/core/assets/url_asset.py @@ -1,13 +1,13 @@ # generated by datamodel-codegen: # filename: core/assets/url_asset.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations -from typing import Annotated +from typing import Annotated, Literal from adcp.types.base import AdCPBaseModel -from pydantic import AnyUrl, ConfigDict, Field +from pydantic import ConfigDict, Field from ...enums import url_asset_type from .. import provenance as provenance_1 @@ -17,7 +17,18 @@ class UrlAsset(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - url: Annotated[AnyUrl, Field(description="URL reference")] + asset_type: Annotated[ + Literal["url"], + Field( + description="Discriminator identifying this as a URL asset. See /schemas/creative/asset-types for the registry." + ), + ] = "url" + url: Annotated[ + str, + Field( + description="URL reference. May be a plain URI or an RFC 6570 URI template carrying AdCP universal macros (e.g., `{SKU}`, `{MEDIA_BUY_ID}`). Buyers MUST NOT pre-encode macro braces at sync time; the ad server URL-encodes substituted values at impression time. See docs/creative/universal-macros.mdx." + ), + ] 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 523f4b0f9..a9283c1e2 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -18,11 +18,12 @@ class VastAsset1(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["url"], - Field(description="Discriminator indicating VAST is delivered via URL endpoint"), - ] - url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ vast_version_1.VastVersion | None, Field(description="VAST specification version") ] = None @@ -50,17 +51,23 @@ class VastAsset1(AdCPBaseModel): description="Provenance metadata for this asset, overrides manifest-level provenance" ), ] = None + delivery_type: Annotated[ + Literal["url"], + Field(description="Discriminator indicating VAST is delivered via URL endpoint"), + ] = "url" + url: Annotated[AnyUrl, Field(description="URL endpoint that returns VAST XML")] class VastAsset2(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - delivery_type: Annotated[ - Literal["inline"], - Field(description="Discriminator indicating VAST is delivered as inline XML content"), - ] - content: Annotated[str, Field(description="Inline VAST XML content")] + asset_type: Annotated[ + Literal["vast"], + Field( + description="Discriminator identifying this as a VAST asset. See /schemas/creative/asset-types for the registry." + ), + ] = "vast" vast_version: Annotated[ vast_version_1.VastVersion | None, Field(description="VAST specification version") ] = None @@ -88,6 +95,11 @@ class VastAsset2(AdCPBaseModel): description="Provenance metadata for this asset, overrides manifest-level provenance" ), ] = None + delivery_type: Annotated[ + Literal["inline"], + Field(description="Discriminator indicating VAST is delivered as inline XML content"), + ] = "inline" + content: Annotated[str, Field(description="Inline VAST XML content")] class VastAsset(RootModel[VastAsset1 | VastAsset2]): @@ -95,6 +107,7 @@ class VastAsset(RootModel[VastAsset1 | VastAsset2]): VastAsset1 | VastAsset2, Field( description="VAST (Video Ad Serving Template) tag for third-party video ad serving", + discriminator="delivery_type", 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 ec669ecc8..626043c6a 100644 --- a/src/adcp/types/generated_poc/core/assets/video_asset.py +++ b/src/adcp/types/generated_poc/core/assets/video_asset.py @@ -1,11 +1,11 @@ # generated by datamodel-codegen: # filename: core/assets/video_asset.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations from enum import Enum, IntEnum -from typing import Annotated +from typing import Annotated, Literal from adcp.types.base import AdCPBaseModel from pydantic import AnyUrl, ConfigDict, Field @@ -78,6 +78,12 @@ class VideoAsset(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["video"], + Field( + description="Discriminator identifying this as a video asset. See /schemas/creative/asset-types for the registry." + ), + ] = "video" 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)] 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 be012575f..fcde873a9 100644 --- a/src/adcp/types/generated_poc/core/assets/webhook_asset.py +++ b/src/adcp/types/generated_poc/core/assets/webhook_asset.py @@ -1,10 +1,10 @@ # generated by datamodel-codegen: # filename: core/assets/webhook_asset.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations -from typing import Annotated +from typing import Annotated, Literal from adcp.types.base import AdCPBaseModel from pydantic import AnyUrl, ConfigDict, Field @@ -29,6 +29,12 @@ class WebhookAsset(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) + asset_type: Annotated[ + Literal["webhook"], + Field( + description="Discriminator identifying this as a webhook asset. See /schemas/creative/asset-types for the registry." + ), + ] = "webhook" url: Annotated[AnyUrl, Field(description="Webhook URL to call for dynamic content")] method: Annotated[http_method.HttpMethod | None, Field(description="HTTP method")] = ( http_method.HttpMethod.POST 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 6d1a5af24..8d84341aa 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: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/attribution_window.py b/src/adcp/types/generated_poc/core/attribution_window.py index 7c55e859c..12f5b58ba 100644 --- a/src/adcp/types/generated_poc/core/attribution_window.py +++ b/src/adcp/types/generated_poc/core/attribution_window.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/attribution_window.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/audience_member.py b/src/adcp/types/generated_poc/core/audience_member.py index 50686312f..5819727fb 100644 --- a/src/adcp/types/generated_poc/core/audience_member.py +++ b/src/adcp/types/generated_poc/core/audience_member.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/audience_member.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/audience_selector.py b/src/adcp/types/generated_poc/core/audience_selector.py index b53adc0a5..03a159d4e 100644 --- a/src/adcp/types/generated_poc/core/audience_selector.py +++ b/src/adcp/types/generated_poc/core/audience_selector.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/audience_selector.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -18,7 +18,7 @@ class AudienceSelector4(AdCPBaseModel): ) type: Annotated[ Literal["description"], Field(description="Discriminator for description-based selectors") - ] + ] = "description" description: Annotated[ str, Field( @@ -41,9 +41,11 @@ class AudienceSelector1(AdCPBaseModel): ) type: Annotated[ Literal["signal"], Field(description="Discriminator for signal-based selectors") - ] + ] = "signal" signal_id: Annotated[signal_id_1.SignalId, Field(description="The signal to target")] - value_type: Annotated[Literal["binary"], Field(description="Discriminator for binary signals")] + value_type: Annotated[ + Literal["binary"], Field(description="Discriminator for binary signals") + ] = "binary" value: Annotated[ bool, Field( @@ -58,11 +60,11 @@ class AudienceSelector2(AdCPBaseModel): ) type: Annotated[ Literal["signal"], Field(description="Discriminator for signal-based selectors") - ] + ] = "signal" signal_id: Annotated[signal_id_1.SignalId, Field(description="The signal to target")] value_type: Annotated[ Literal["categorical"], Field(description="Discriminator for categorical signals") - ] + ] = "categorical" values: Annotated[ list[str], Field( @@ -78,11 +80,11 @@ class AudienceSelector3(AdCPBaseModel): ) type: Annotated[ Literal["signal"], Field(description="Discriminator for signal-based selectors") - ] + ] = "signal" signal_id: Annotated[signal_id_1.SignalId, Field(description="The signal to target")] value_type: Annotated[ Literal["numeric"], Field(description="Discriminator for numeric signals") - ] + ] = "numeric" min_value: Annotated[ float | None, Field( diff --git a/src/adcp/types/generated_poc/core/brand_id.py b/src/adcp/types/generated_poc/core/brand_id.py index 8046ba62a..b38824ff2 100644 --- a/src/adcp/types/generated_poc/core/brand_id.py +++ b/src/adcp/types/generated_poc/core/brand_id.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/brand_id.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/brand_ref.py b/src/adcp/types/generated_poc/core/brand_ref.py index 91b8cffd1..245cb8722 100644 --- a/src/adcp/types/generated_poc/core/brand_ref.py +++ b/src/adcp/types/generated_poc/core/brand_ref.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/brand_ref.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/business_entity.py b/src/adcp/types/generated_poc/core/business_entity.py index 88ab5f05b..b2e2cc4ad 100644 --- a/src/adcp/types/generated_poc/core/business_entity.py +++ b/src/adcp/types/generated_poc/core/business_entity.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/business_entity.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/cancellation_policy.py b/src/adcp/types/generated_poc/core/cancellation_policy.py index 2ba5adf42..aedd9943a 100644 --- a/src/adcp/types/generated_poc/core/cancellation_policy.py +++ b/src/adcp/types/generated_poc/core/cancellation_policy.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/cancellation_policy.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/catalog.py b/src/adcp/types/generated_poc/core/catalog.py index 66153d729..b43842d84 100644 --- a/src/adcp/types/generated_poc/core/catalog.py +++ b/src/adcp/types/generated_poc/core/catalog.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/catalog.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/catalog_field_mapping.py b/src/adcp/types/generated_poc/core/catalog_field_mapping.py index 701729c85..c7a551572 100644 --- a/src/adcp/types/generated_poc/core/catalog_field_mapping.py +++ b/src/adcp/types/generated_poc/core/catalog_field_mapping.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/catalog_field_mapping.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/catchment.py b/src/adcp/types/generated_poc/core/catchment.py index 5e7e2299a..96e89cf6d 100644 --- a/src/adcp/types/generated_poc/core/catchment.py +++ b/src/adcp/types/generated_poc/core/catchment.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/catchment.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/collection.py b/src/adcp/types/generated_poc/core/collection.py index b3929e735..51d092308 100644 --- a/src/adcp/types/generated_poc/core/collection.py +++ b/src/adcp/types/generated_poc/core/collection.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/collection.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/collection_distribution.py b/src/adcp/types/generated_poc/core/collection_distribution.py index 1de40811f..47ca63364 100644 --- a/src/adcp/types/generated_poc/core/collection_distribution.py +++ b/src/adcp/types/generated_poc/core/collection_distribution.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/collection_distribution.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/collection_list_ref.py b/src/adcp/types/generated_poc/core/collection_list_ref.py index 31bd04a49..7c89dc7cd 100644 --- a/src/adcp/types/generated_poc/core/collection_list_ref.py +++ b/src/adcp/types/generated_poc/core/collection_list_ref.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/collection_list_ref.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/collection_selector.py b/src/adcp/types/generated_poc/core/collection_selector.py index ce9922fa5..457097752 100644 --- a/src/adcp/types/generated_poc/core/collection_selector.py +++ b/src/adcp/types/generated_poc/core/collection_selector.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/collection_selector.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/content_rating.py b/src/adcp/types/generated_poc/core/content_rating.py index 1a339eb2a..8fb1cf31e 100644 --- a/src/adcp/types/generated_poc/core/content_rating.py +++ b/src/adcp/types/generated_poc/core/content_rating.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/content_rating.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/context.py b/src/adcp/types/generated_poc/core/context.py index a56ba9d7b..f0f1ec4c2 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/creative_asset.py b/src/adcp/types/generated_poc/core/creative_asset.py index 1b3adee26..ae9920d29 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -75,7 +75,9 @@ class CreativeAsset(AdCPBaseModel): | brief_asset.BriefAsset | catalog_asset.CatalogAsset, ], - Field(description="Assets required by the format, keyed by asset_id"), + Field( + description="Assets required by the format, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema." + ), ] inputs: Annotated[ list[Input] | None, diff --git a/src/adcp/types/generated_poc/core/creative_assignment.py b/src/adcp/types/generated_poc/core/creative_assignment.py index 6c9e99857..55de53e1a 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/creative_brief.py b/src/adcp/types/generated_poc/core/creative_brief.py index 45ad1973f..9c4f21767 100644 --- a/src/adcp/types/generated_poc/core/creative_brief.py +++ b/src/adcp/types/generated_poc/core/creative_brief.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_brief.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/creative_consumption.py b/src/adcp/types/generated_poc/core/creative_consumption.py index 7dc9be2dc..1d7b461ca 100644 --- a/src/adcp/types/generated_poc/core/creative_consumption.py +++ b/src/adcp/types/generated_poc/core/creative_consumption.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_consumption.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/creative_filters.py b/src/adcp/types/generated_poc/core/creative_filters.py index 9b6056614..4986167f3 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/creative_item.py b/src/adcp/types/generated_poc/core/creative_item.py index ce8116e1d..4d0651baf 100644 --- a/src/adcp/types/generated_poc/core/creative_item.py +++ b/src/adcp/types/generated_poc/core/creative_item.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_item.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class CreativeItem1(AdCPBaseModel): asset_kind: Annotated[ Literal["media"], Field(description="Discriminator indicating this is a media asset with content_uri"), - ] + ] = "media" asset_type: Annotated[ str, Field( @@ -37,7 +37,7 @@ class CreativeItem2(AdCPBaseModel): asset_kind: Annotated[ Literal["text"], Field(description="Discriminator indicating this is a text asset with content"), - ] + ] = "text" asset_type: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/core/creative_manifest.py b/src/adcp/types/generated_poc/core/creative_manifest.py index 6b5270f1e..5abc00504 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-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -61,7 +61,7 @@ class CreativeManifest(AdCPBaseModel): | catalog_asset.CatalogAsset, ], Field( - description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance — each asset must match at least one valid asset type schema." + description="Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nEach asset value carries an `asset_type` discriminator (image, video, audio, vast, daast, text, markdown, url, html, css, webhook, javascript, brief, catalog) that selects the matching asset schema. Validators with OpenAPI-style discriminator support use `asset_type` to report errors against only the selected branch instead of all branches." ), ] rights: Annotated[ diff --git a/src/adcp/types/generated_poc/core/creative_policy.py b/src/adcp/types/generated_poc/core/creative_policy.py index 4df1415d5..f8cb4065d 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/creative_variable.py b/src/adcp/types/generated_poc/core/creative_variable.py index 3b1951384..4bd20a05d 100644 --- a/src/adcp/types/generated_poc/core/creative_variable.py +++ b/src/adcp/types/generated_poc/core/creative_variable.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_variable.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/creative_variant.py b/src/adcp/types/generated_poc/core/creative_variant.py index bdece66df..18400fcd8 100644 --- a/src/adcp/types/generated_poc/core/creative_variant.py +++ b/src/adcp/types/generated_poc/core/creative_variant.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/creative_variant.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/data_provider_signal_selector.py b/src/adcp/types/generated_poc/core/data_provider_signal_selector.py index 219a8a7a3..f2193a0fd 100644 --- a/src/adcp/types/generated_poc/core/data_provider_signal_selector.py +++ b/src/adcp/types/generated_poc/core/data_provider_signal_selector.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/data_provider_signal_selector.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -26,7 +26,7 @@ class DataProviderSignalSelector1(AdCPBaseModel): Field( description="Discriminator indicating all signals from this data provider are included" ), - ] + ] = "all" class SignalId(RootModel[str]): @@ -47,7 +47,7 @@ class DataProviderSignalSelector2(AdCPBaseModel): selection_type: Annotated[ Literal["by_id"], Field(description="Discriminator indicating selection by specific signal IDs"), - ] + ] = "by_id" signal_ids: Annotated[ list[SignalId], Field(description="Specific signal IDs from the data provider's catalog", min_length=1), @@ -71,7 +71,7 @@ class DataProviderSignalSelector3(AdCPBaseModel): ] selection_type: Annotated[ Literal["by_tag"], Field(description="Discriminator indicating selection by signal tags") - ] + ] = "by_tag" signal_tags: Annotated[ list[SignalTag], Field( diff --git a/src/adcp/types/generated_poc/core/date_range.py b/src/adcp/types/generated_poc/core/date_range.py index 91dfb731e..6059c1b0b 100644 --- a/src/adcp/types/generated_poc/core/date_range.py +++ b/src/adcp/types/generated_poc/core/date_range.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/date_range.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/datetime_range.py b/src/adcp/types/generated_poc/core/datetime_range.py index 39f95aa96..091e9aba2 100644 --- a/src/adcp/types/generated_poc/core/datetime_range.py +++ b/src/adcp/types/generated_poc/core/datetime_range.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/datetime_range.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/daypart_target.py b/src/adcp/types/generated_poc/core/daypart_target.py index c44af0ad7..f3c3b9fa2 100644 --- a/src/adcp/types/generated_poc/core/daypart_target.py +++ b/src/adcp/types/generated_poc/core/daypart_target.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/daypart_target.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/deadline_policy.py b/src/adcp/types/generated_poc/core/deadline_policy.py index 9944fa1fc..a87d1c2a6 100644 --- a/src/adcp/types/generated_poc/core/deadline_policy.py +++ b/src/adcp/types/generated_poc/core/deadline_policy.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/deadline_policy.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/delivery_forecast.py b/src/adcp/types/generated_poc/core/delivery_forecast.py index 0f763c8a1..467fabcf8 100644 --- a/src/adcp/types/generated_poc/core/delivery_forecast.py +++ b/src/adcp/types/generated_poc/core/delivery_forecast.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/delivery_forecast.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/delivery_metrics.py b/src/adcp/types/generated_poc/core/delivery_metrics.py index ba3afb1fe..369b3eb17 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/deployment.py b/src/adcp/types/generated_poc/core/deployment.py index 6105ad5d0..61c414b32 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -19,7 +19,7 @@ class Deployment1(AdCPBaseModel): type: Annotated[ Literal["platform"], Field(description="Discriminator indicating this is a platform-based deployment"), - ] + ] = "platform" platform: Annotated[str, Field(description="Platform identifier for DSPs")] account: Annotated[str | None, Field(description="Account identifier if applicable")] = None is_live: Annotated[ @@ -51,7 +51,7 @@ class Deployment2(AdCPBaseModel): type: Annotated[ Literal["agent"], Field(description="Discriminator indicating this is an agent URL-based deployment"), - ] + ] = "agent" agent_url: Annotated[AnyUrl, Field(description="URL identifying the deployment agent")] account: Annotated[str | None, Field(description="Account identifier if applicable")] = None is_live: Annotated[ diff --git a/src/adcp/types/generated_poc/core/destination.py b/src/adcp/types/generated_poc/core/destination.py index d8d152b04..c4185fa20 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class Destination1(AdCPBaseModel): type: Annotated[ Literal["platform"], Field(description="Discriminator indicating this is a platform-based deployment"), - ] + ] = "platform" platform: Annotated[ str, Field(description="Platform identifier for DSPs (e.g., 'the-trade-desk', 'amazon-dsp')"), @@ -34,7 +34,7 @@ class Destination2(AdCPBaseModel): type: Annotated[ Literal["agent"], Field(description="Discriminator indicating this is an agent URL-based deployment"), - ] + ] = "agent" agent_url: Annotated[ AnyUrl, Field(description="URL identifying the deployment agent (for sales agents, etc.)") ] diff --git a/src/adcp/types/generated_poc/core/destination_item.py b/src/adcp/types/generated_poc/core/destination_item.py index 7689cfe9f..d8ef318c4 100644 --- a/src/adcp/types/generated_poc/core/destination_item.py +++ b/src/adcp/types/generated_poc/core/destination_item.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/destination_item.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/diagnostic_issue.py b/src/adcp/types/generated_poc/core/diagnostic_issue.py index 4d2fd18bb..f8c18623f 100644 --- a/src/adcp/types/generated_poc/core/diagnostic_issue.py +++ b/src/adcp/types/generated_poc/core/diagnostic_issue.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/diagnostic_issue.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/duration.py b/src/adcp/types/generated_poc/core/duration.py index a399bb0f2..e58373aee 100644 --- a/src/adcp/types/generated_poc/core/duration.py +++ b/src/adcp/types/generated_poc/core/duration.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/duration.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/education_item.py b/src/adcp/types/generated_poc/core/education_item.py index b46737602..f05a5404a 100644 --- a/src/adcp/types/generated_poc/core/education_item.py +++ b/src/adcp/types/generated_poc/core/education_item.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/education_item.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/error.py b/src/adcp/types/generated_poc/core/error.py index 69e595937..22d80d0b9 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-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/event.py b/src/adcp/types/generated_poc/core/event.py index e77b72455..902e5cf04 100644 --- a/src/adcp/types/generated_poc/core/event.py +++ b/src/adcp/types/generated_poc/core/event.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/event.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/event_custom_data.py b/src/adcp/types/generated_poc/core/event_custom_data.py index 5053aa85f..98f450a1e 100644 --- a/src/adcp/types/generated_poc/core/event_custom_data.py +++ b/src/adcp/types/generated_poc/core/event_custom_data.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/event_custom_data.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/event_source_health.py b/src/adcp/types/generated_poc/core/event_source_health.py index 600380ced..a5887159a 100644 --- a/src/adcp/types/generated_poc/core/event_source_health.py +++ b/src/adcp/types/generated_poc/core/event_source_health.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/event_source_health.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/ext.py b/src/adcp/types/generated_poc/core/ext.py index c712ed26d..53933cbe3 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/feature_requirement.py b/src/adcp/types/generated_poc/core/feature_requirement.py index ea54b82ff..0f040af1a 100644 --- a/src/adcp/types/generated_poc/core/feature_requirement.py +++ b/src/adcp/types/generated_poc/core/feature_requirement.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/feature_requirement.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/flight_item.py b/src/adcp/types/generated_poc/core/flight_item.py index b39516454..4264dc241 100644 --- a/src/adcp/types/generated_poc/core/flight_item.py +++ b/src/adcp/types/generated_poc/core/flight_item.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/flight_item.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/forecast_point.py b/src/adcp/types/generated_poc/core/forecast_point.py index 6694e8822..fa374ff55 100644 --- a/src/adcp/types/generated_poc/core/forecast_point.py +++ b/src/adcp/types/generated_poc/core/forecast_point.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/forecast_point.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/forecast_range.py b/src/adcp/types/generated_poc/core/forecast_range.py index 030267945..2e7f97826 100644 --- a/src/adcp/types/generated_poc/core/forecast_range.py +++ b/src/adcp/types/generated_poc/core/forecast_range.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/forecast_range.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/format.py b/src/adcp/types/generated_poc/core/format.py index d858465a7..95fc25e31 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -201,7 +201,7 @@ class BaseIndividualAsset(AdCPBaseModel): item_type: Annotated[ Literal["individual"], Field(description="Discriminator indicating this is an individual asset"), - ] + ] = "individual" asset_id: Annotated[ str, Field( @@ -395,7 +395,7 @@ class Assets94(AdCPBaseModel): item_type: Annotated[ Literal["repeatable_group"], Field(description="Discriminator indicating this is a repeatable asset group"), - ] + ] = "repeatable_group" asset_group_id: Annotated[ str, Field(description="Identifier for this asset group (e.g., 'product', 'slide', 'card')") ] diff --git a/src/adcp/types/generated_poc/core/format_id.py b/src/adcp/types/generated_poc/core/format_id.py index e3a545dc8..f1b8c23bb 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/frequency_cap.py b/src/adcp/types/generated_poc/core/frequency_cap.py index 29271f770..c411da69c 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/generation_credential.py b/src/adcp/types/generated_poc/core/generation_credential.py index b47f864d5..68ddd108c 100644 --- a/src/adcp/types/generated_poc/core/generation_credential.py +++ b/src/adcp/types/generated_poc/core/generation_credential.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/generation_credential.json -# timestamp: 2026-04-18T20:45:21+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/geo_breakdown_support.py b/src/adcp/types/generated_poc/core/geo_breakdown_support.py index 5587b82fd..388a8753b 100644 --- a/src/adcp/types/generated_poc/core/geo_breakdown_support.py +++ b/src/adcp/types/generated_poc/core/geo_breakdown_support.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/geo_breakdown_support.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/hotel_item.py b/src/adcp/types/generated_poc/core/hotel_item.py index 1bc042f40..3bb58c75b 100644 --- a/src/adcp/types/generated_poc/core/hotel_item.py +++ b/src/adcp/types/generated_poc/core/hotel_item.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/hotel_item.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/identifier.py b/src/adcp/types/generated_poc/core/identifier.py index e2ab3ed2d..214c43499 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-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/industry_identifier.py b/src/adcp/types/generated_poc/core/industry_identifier.py index 1d6e510db..4df14ed29 100644 --- a/src/adcp/types/generated_poc/core/industry_identifier.py +++ b/src/adcp/types/generated_poc/core/industry_identifier.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/industry_identifier.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/insertion_order.py b/src/adcp/types/generated_poc/core/insertion_order.py index 3754f1dba..a3e746344 100644 --- a/src/adcp/types/generated_poc/core/insertion_order.py +++ b/src/adcp/types/generated_poc/core/insertion_order.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/insertion_order.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/installment.py b/src/adcp/types/generated_poc/core/installment.py index ad766c8d4..336d49595 100644 --- a/src/adcp/types/generated_poc/core/installment.py +++ b/src/adcp/types/generated_poc/core/installment.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/installment.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/installment_deadlines.py b/src/adcp/types/generated_poc/core/installment_deadlines.py index adbbf2d3e..1bf16395d 100644 --- a/src/adcp/types/generated_poc/core/installment_deadlines.py +++ b/src/adcp/types/generated_poc/core/installment_deadlines.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/installment_deadlines.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/job_item.py b/src/adcp/types/generated_poc/core/job_item.py index a95325f6d..6922eb67f 100644 --- a/src/adcp/types/generated_poc/core/job_item.py +++ b/src/adcp/types/generated_poc/core/job_item.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/job_item.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/limited_series.py b/src/adcp/types/generated_poc/core/limited_series.py index 342ea98b0..fe3d31278 100644 --- a/src/adcp/types/generated_poc/core/limited_series.py +++ b/src/adcp/types/generated_poc/core/limited_series.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/limited_series.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/material_deadline.py b/src/adcp/types/generated_poc/core/material_deadline.py index 41251d5d2..59cb2636a 100644 --- a/src/adcp/types/generated_poc/core/material_deadline.py +++ b/src/adcp/types/generated_poc/core/material_deadline.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/material_deadline.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 c8b6df4d7..e0f4badf8 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: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/measurement_readiness.py b/src/adcp/types/generated_poc/core/measurement_readiness.py index 7839b9fbc..004b7df3b 100644 --- a/src/adcp/types/generated_poc/core/measurement_readiness.py +++ b/src/adcp/types/generated_poc/core/measurement_readiness.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/measurement_readiness.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/measurement_terms.py b/src/adcp/types/generated_poc/core/measurement_terms.py index 2d07a2e6a..d8e8832e5 100644 --- a/src/adcp/types/generated_poc/core/measurement_terms.py +++ b/src/adcp/types/generated_poc/core/measurement_terms.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/measurement_terms.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/measurement_window.py b/src/adcp/types/generated_poc/core/measurement_window.py index cb3007532..1a7d1ac54 100644 --- a/src/adcp/types/generated_poc/core/measurement_window.py +++ b/src/adcp/types/generated_poc/core/measurement_window.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/measurement_window.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/media_buy.py b/src/adcp/types/generated_poc/core/media_buy.py index d0de54cb7..cf71c9308 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/media_buy_features.py b/src/adcp/types/generated_poc/core/media_buy_features.py index 59aa52456..820fb1173 100644 --- a/src/adcp/types/generated_poc/core/media_buy_features.py +++ b/src/adcp/types/generated_poc/core/media_buy_features.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/media_buy_features.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/offering.py b/src/adcp/types/generated_poc/core/offering.py index 463f94ad3..c54192cc0 100644 --- a/src/adcp/types/generated_poc/core/offering.py +++ b/src/adcp/types/generated_poc/core/offering.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/offering.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/offering_asset_group.py b/src/adcp/types/generated_poc/core/offering_asset_group.py index 547227e0e..374e6198b 100644 --- a/src/adcp/types/generated_poc/core/offering_asset_group.py +++ b/src/adcp/types/generated_poc/core/offering_asset_group.py @@ -1,13 +1,13 @@ # generated by datamodel-codegen: # filename: core/offering_asset_group.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations -from typing import Annotated +from typing import Any, Annotated from adcp.types.base import AdCPBaseModel -from pydantic import ConfigDict, Field +from pydantic import ConfigDict, Field, RootModel from ..enums import asset_content_type from . import ext as ext_1 @@ -27,6 +27,45 @@ ) +class Items( + RootModel[ + text_asset.TextAsset + | image_asset.ImageAsset + | video_asset.VideoAsset + | audio_asset.AudioAsset + | url_asset.UrlAsset + | html_asset.HtmlAsset + | markdown_asset.MarkdownAsset + | vast_asset.VastAsset + | daast_asset.DaastAsset + | css_asset.CssAsset + | javascript_asset.JavascriptAsset + | webhook_asset.WebhookAsset + ] +): + root: Annotated[ + text_asset.TextAsset + | image_asset.ImageAsset + | video_asset.VideoAsset + | audio_asset.AudioAsset + | url_asset.UrlAsset + | html_asset.HtmlAsset + | markdown_asset.MarkdownAsset + | vast_asset.VastAsset + | daast_asset.DaastAsset + | css_asset.CssAsset + | javascript_asset.JavascriptAsset + | webhook_asset.WebhookAsset, + Field(discriminator="asset_type"), + ] + + def __getattr__(self, name: str) -> Any: + """Proxy attribute access to the wrapped type.""" + if name.startswith("_"): + raise AttributeError(name) + return getattr(self.root, name) + + class OfferingAssetGroup(AdCPBaseModel): model_config = ConfigDict( extra="allow", @@ -42,22 +81,9 @@ class OfferingAssetGroup(AdCPBaseModel): Field(description="The content type of all items in this group."), ] items: Annotated[ - list[ - text_asset.TextAsset - | image_asset.ImageAsset - | video_asset.VideoAsset - | audio_asset.AudioAsset - | url_asset.UrlAsset - | html_asset.HtmlAsset - | markdown_asset.MarkdownAsset - | vast_asset.VastAsset - | daast_asset.DaastAsset - | css_asset.CssAsset - | javascript_asset.JavascriptAsset - | webhook_asset.WebhookAsset - ], + list[Items], Field( - description="The assets in this group. Each item should match the structure for the declared asset_type. Note: JSON Schema validation accepts any valid asset structure here; enforcement that items match asset_type is the responsibility of the consuming agent.", + description="The assets in this group. Each item carries an `asset_type` discriminator that selects the matching asset schema. Note: the group-level `asset_type` declares the expected type; individual items must also self-tag so validators can narrow errors.", min_length=1, ), ] diff --git a/src/adcp/types/generated_poc/core/optimization_goal.py b/src/adcp/types/generated_poc/core/optimization_goal.py index 6049fa3a5..1c54029a4 100644 --- a/src/adcp/types/generated_poc/core/optimization_goal.py +++ b/src/adcp/types/generated_poc/core/optimization_goal.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/optimization_goal.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -85,7 +85,7 @@ class Target(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["cost_per"] + kind: Literal["cost_per"] = "cost_per" value: Annotated[ float, Field(description="Target cost per metric unit in the buy currency", gt=0.0) ] @@ -95,7 +95,7 @@ class Target11(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["threshold_rate"] + kind: Literal["threshold_rate"] = "threshold_rate" value: Annotated[ float, Field( @@ -146,7 +146,7 @@ class Target12(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["cost_per"] + kind: Literal["cost_per"] = "cost_per" value: Annotated[float, Field(description="Target cost per event in the buy currency", gt=0.0)] @@ -154,7 +154,7 @@ class Target13(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["per_ad_spend"] + kind: Literal["per_ad_spend"] = "per_ad_spend" value: Annotated[ float, Field(description="Target return ratio (e.g., 4.0 means $4 of value per $1 spent)", gt=0.0), @@ -165,7 +165,7 @@ class Target14(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["maximize_value"] + kind: Literal["maximize_value"] = "maximize_value" class AttributionWindow(AdCPBaseModel): @@ -190,7 +190,7 @@ class OptimizationGoal2(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["event"] + kind: Literal["event"] = "event" event_sources: Annotated[ list[EventSource], Field( @@ -223,7 +223,7 @@ class OptimizationGoal1(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["metric"] + kind: Literal["metric"] = "metric" metric: Annotated[ Metric, Field( diff --git a/src/adcp/types/generated_poc/core/outcome_measurement.py b/src/adcp/types/generated_poc/core/outcome_measurement.py index 25527e7fb..9950682df 100644 --- a/src/adcp/types/generated_poc/core/outcome_measurement.py +++ b/src/adcp/types/generated_poc/core/outcome_measurement.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/outcome_measurement.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/overlay.py b/src/adcp/types/generated_poc/core/overlay.py index a2e4c488d..454a09f82 100644 --- a/src/adcp/types/generated_poc/core/overlay.py +++ b/src/adcp/types/generated_poc/core/overlay.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/overlay.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/package.py b/src/adcp/types/generated_poc/core/package.py index b4f75a2c7..186645414 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/pagination_request.py b/src/adcp/types/generated_poc/core/pagination_request.py index a1255cc44..4e62d3e4b 100644 --- a/src/adcp/types/generated_poc/core/pagination_request.py +++ b/src/adcp/types/generated_poc/core/pagination_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/pagination_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/pagination_response.py b/src/adcp/types/generated_poc/core/pagination_response.py index 3d18c1d77..1fc9b559a 100644 --- a/src/adcp/types/generated_poc/core/pagination_response.py +++ b/src/adcp/types/generated_poc/core/pagination_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/pagination_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/performance_feedback.py b/src/adcp/types/generated_poc/core/performance_feedback.py index c6e3ce7d4..c6b387180 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/performance_standard.py b/src/adcp/types/generated_poc/core/performance_standard.py index 75139f89c..c4d60ae3a 100644 --- a/src/adcp/types/generated_poc/core/performance_standard.py +++ b/src/adcp/types/generated_poc/core/performance_standard.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/performance_standard.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/placement.py b/src/adcp/types/generated_poc/core/placement.py index 8d85ab727..a65254552 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/placement_definition.py b/src/adcp/types/generated_poc/core/placement_definition.py index bbe2b4226..c8d2ebd6e 100644 --- a/src/adcp/types/generated_poc/core/placement_definition.py +++ b/src/adcp/types/generated_poc/core/placement_definition.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/placement_definition.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/planned_delivery.py b/src/adcp/types/generated_poc/core/planned_delivery.py index 0b1f646a8..fb2d5670c 100644 --- a/src/adcp/types/generated_poc/core/planned_delivery.py +++ b/src/adcp/types/generated_poc/core/planned_delivery.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/planned_delivery.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/price.py b/src/adcp/types/generated_poc/core/price.py index e576d35ee..987460e14 100644 --- a/src/adcp/types/generated_poc/core/price.py +++ b/src/adcp/types/generated_poc/core/price.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/price.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/pricing_option.py b/src/adcp/types/generated_poc/core/pricing_option.py index 4b8c88a8f..023142bf1 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-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/product.py b/src/adcp/types/generated_poc/core/product.py index 62d8406f4..8124960b9 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/product_allocation.py b/src/adcp/types/generated_poc/core/product_allocation.py index e1f644b68..e586b3bbe 100644 --- a/src/adcp/types/generated_poc/core/product_allocation.py +++ b/src/adcp/types/generated_poc/core/product_allocation.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/product_allocation.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/product_filters.py b/src/adcp/types/generated_poc/core/product_filters.py index 081059d1e..b06c73b0b 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-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/property.py b/src/adcp/types/generated_poc/core/property.py index 018ca04b3..7a1346be3 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/property_id.py b/src/adcp/types/generated_poc/core/property_id.py index b2b319645..44d976f57 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 a66c92ad1..3b61ceff9 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/property_tag.py b/src/adcp/types/generated_poc/core/property_tag.py index 2dc9564cb..1bbcd6365 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/proposal.py b/src/adcp/types/generated_poc/core/proposal.py index 144d80f08..ec0e518d8 100644 --- a/src/adcp/types/generated_poc/core/proposal.py +++ b/src/adcp/types/generated_poc/core/proposal.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/proposal.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/protocol_envelope.py b/src/adcp/types/generated_poc/core/protocol_envelope.py index 2ed08c82b..e6e3a02c3 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/provenance.py b/src/adcp/types/generated_poc/core/provenance.py index 53dd53ca7..85b060942 100644 --- a/src/adcp/types/generated_poc/core/provenance.py +++ b/src/adcp/types/generated_poc/core/provenance.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/provenance.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 d4f919bb4..d904ccd79 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -28,7 +28,7 @@ class PublisherPropertySelector1(AdCPBaseModel): Field( description="Discriminator indicating all properties from this publisher are included" ), - ] + ] = "all" class PublisherPropertySelector2(AdCPBaseModel): @@ -45,7 +45,7 @@ class PublisherPropertySelector2(AdCPBaseModel): selection_type: Annotated[ Literal["by_id"], Field(description="Discriminator indicating selection by specific property IDs"), - ] + ] = "by_id" property_ids: Annotated[ list[property_id.PropertyId], Field(description="Specific property IDs from the publisher's adagents.json", min_length=1), @@ -65,7 +65,7 @@ class PublisherPropertySelector3(AdCPBaseModel): ] selection_type: Annotated[ Literal["by_tag"], Field(description="Discriminator indicating selection by property tags") - ] + ] = "by_tag" property_tags: Annotated[ list[property_tag.PropertyTag], Field( 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 012bbf3b1..905a3ad22 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: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/real_estate_item.py b/src/adcp/types/generated_poc/core/real_estate_item.py index 150829779..724db5fc1 100644 --- a/src/adcp/types/generated_poc/core/real_estate_item.py +++ b/src/adcp/types/generated_poc/core/real_estate_item.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/real_estate_item.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/reference_asset.py b/src/adcp/types/generated_poc/core/reference_asset.py index e57f054f7..5687267ad 100644 --- a/src/adcp/types/generated_poc/core/reference_asset.py +++ b/src/adcp/types/generated_poc/core/reference_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/reference_asset.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/reporting_capabilities.py b/src/adcp/types/generated_poc/core/reporting_capabilities.py index e55125d8a..e80ac279f 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/reporting_webhook.py b/src/adcp/types/generated_poc/core/reporting_webhook.py index 0d4a71144..602df503e 100644 --- a/src/adcp/types/generated_poc/core/reporting_webhook.py +++ b/src/adcp/types/generated_poc/core/reporting_webhook.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/reporting_webhook.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/asset_requirements.py b/src/adcp/types/generated_poc/core/requirements/asset_requirements.py index 0db67f300..e1d77f7a7 100644 --- a/src/adcp/types/generated_poc/core/requirements/asset_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/asset_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/asset_requirements.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/audio_asset_requirements.py b/src/adcp/types/generated_poc/core/requirements/audio_asset_requirements.py index 6be18be51..b82ff045e 100644 --- a/src/adcp/types/generated_poc/core/requirements/audio_asset_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/audio_asset_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/audio_asset_requirements.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/catalog_field_binding.py b/src/adcp/types/generated_poc/core/requirements/catalog_field_binding.py index 2e16b4f51..b3a6f2677 100644 --- a/src/adcp/types/generated_poc/core/requirements/catalog_field_binding.py +++ b/src/adcp/types/generated_poc/core/requirements/catalog_field_binding.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/catalog_field_binding.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -16,7 +16,7 @@ class ScalarBinding(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["scalar"] + kind: Literal["scalar"] = "scalar" asset_id: Annotated[ str, Field( @@ -36,7 +36,7 @@ class AssetPoolBinding(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["asset_pool"] + kind: Literal["asset_pool"] = "asset_pool" asset_id: Annotated[ str, Field( @@ -56,7 +56,7 @@ class CatalogFieldBinding1(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - kind: Literal["catalog_group"] + kind: Literal["catalog_group"] = "catalog_group" format_group_id: Annotated[ str, Field(description="The asset_group_id of a repeatable_group in the format's assets array."), diff --git a/src/adcp/types/generated_poc/core/requirements/catalog_requirements.py b/src/adcp/types/generated_poc/core/requirements/catalog_requirements.py index 28d093e54..e96cdc813 100644 --- a/src/adcp/types/generated_poc/core/requirements/catalog_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/catalog_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/catalog_requirements.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/css_asset_requirements.py b/src/adcp/types/generated_poc/core/requirements/css_asset_requirements.py index afad9dfc7..bb6105ed5 100644 --- a/src/adcp/types/generated_poc/core/requirements/css_asset_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/css_asset_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/css_asset_requirements.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/daast_asset_requirements.py b/src/adcp/types/generated_poc/core/requirements/daast_asset_requirements.py index 64a11446c..ce9268d40 100644 --- a/src/adcp/types/generated_poc/core/requirements/daast_asset_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/daast_asset_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/daast_asset_requirements.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/html_asset_requirements.py b/src/adcp/types/generated_poc/core/requirements/html_asset_requirements.py index 280f2c989..386545cbb 100644 --- a/src/adcp/types/generated_poc/core/requirements/html_asset_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/html_asset_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/html_asset_requirements.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/image_asset_requirements.py b/src/adcp/types/generated_poc/core/requirements/image_asset_requirements.py index fd7ba261b..5c98a2118 100644 --- a/src/adcp/types/generated_poc/core/requirements/image_asset_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/image_asset_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/image_asset_requirements.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/javascript_asset_requirements.py b/src/adcp/types/generated_poc/core/requirements/javascript_asset_requirements.py index e7330cb15..5ee4219c9 100644 --- a/src/adcp/types/generated_poc/core/requirements/javascript_asset_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/javascript_asset_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/javascript_asset_requirements.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/markdown_asset_requirements.py b/src/adcp/types/generated_poc/core/requirements/markdown_asset_requirements.py index 027e8e5f4..b6d108321 100644 --- a/src/adcp/types/generated_poc/core/requirements/markdown_asset_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/markdown_asset_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/markdown_asset_requirements.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/offering_asset_constraint.py b/src/adcp/types/generated_poc/core/requirements/offering_asset_constraint.py index 65392e4b3..e9c766c0a 100644 --- a/src/adcp/types/generated_poc/core/requirements/offering_asset_constraint.py +++ b/src/adcp/types/generated_poc/core/requirements/offering_asset_constraint.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/offering_asset_constraint.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/text_asset_requirements.py b/src/adcp/types/generated_poc/core/requirements/text_asset_requirements.py index 8bfb735ef..d7212753c 100644 --- a/src/adcp/types/generated_poc/core/requirements/text_asset_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/text_asset_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/text_asset_requirements.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/url_asset_requirements.py b/src/adcp/types/generated_poc/core/requirements/url_asset_requirements.py index 2874714d3..561649881 100644 --- a/src/adcp/types/generated_poc/core/requirements/url_asset_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/url_asset_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/url_asset_requirements.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/vast_asset_requirements.py b/src/adcp/types/generated_poc/core/requirements/vast_asset_requirements.py index ed1dee053..6b2a6250a 100644 --- a/src/adcp/types/generated_poc/core/requirements/vast_asset_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/vast_asset_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/vast_asset_requirements.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/video_asset_requirements.py b/src/adcp/types/generated_poc/core/requirements/video_asset_requirements.py index ccf9187d1..d3cebb1e3 100644 --- a/src/adcp/types/generated_poc/core/requirements/video_asset_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/video_asset_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/video_asset_requirements.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/requirements/webhook_asset_requirements.py b/src/adcp/types/generated_poc/core/requirements/webhook_asset_requirements.py index 05b848ae4..93e41a9b5 100644 --- a/src/adcp/types/generated_poc/core/requirements/webhook_asset_requirements.py +++ b/src/adcp/types/generated_poc/core/requirements/webhook_asset_requirements.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/requirements/webhook_asset_requirements.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/response.py b/src/adcp/types/generated_poc/core/response.py index 1d90a016f..97b3d1119 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/rights_constraint.py b/src/adcp/types/generated_poc/core/rights_constraint.py index e00e30ff4..c79dc0ee6 100644 --- a/src/adcp/types/generated_poc/core/rights_constraint.py +++ b/src/adcp/types/generated_poc/core/rights_constraint.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/rights_constraint.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/signal_definition.py b/src/adcp/types/generated_poc/core/signal_definition.py index e7aeb6c81..521b54e7e 100644 --- a/src/adcp/types/generated_poc/core/signal_definition.py +++ b/src/adcp/types/generated_poc/core/signal_definition.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/signal_definition.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/signal_filters.py b/src/adcp/types/generated_poc/core/signal_filters.py index da4df5f29..5003afae1 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-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/signal_id.py b/src/adcp/types/generated_poc/core/signal_id.py index 1e0bef6b1..d5184df6e 100644 --- a/src/adcp/types/generated_poc/core/signal_id.py +++ b/src/adcp/types/generated_poc/core/signal_id.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/signal_id.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -19,7 +19,7 @@ class SignalId17(AdCPBaseModel): Field( description="Discriminator indicating this signal is from a data provider's published catalog" ), - ] + ] = "catalog" data_provider_domain: Annotated[ str, Field( @@ -45,7 +45,7 @@ class SignalId18(AdCPBaseModel): Field( description="Discriminator indicating this signal is native to the agent (not from a data provider catalog)" ), - ] + ] = "agent" agent_url: Annotated[ AnyUrl, Field( diff --git a/src/adcp/types/generated_poc/core/signal_pricing.py b/src/adcp/types/generated_poc/core/signal_pricing.py index 492081c66..08a840907 100644 --- a/src/adcp/types/generated_poc/core/signal_pricing.py +++ b/src/adcp/types/generated_poc/core/signal_pricing.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/signal_pricing.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class VendorPricing1(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["cpm"] + model: Literal["cpm"] = "cpm" cpm: Annotated[float, Field(description="Cost per thousand impressions", ge=0.0)] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] ext: ext_1.ExtensionObject | None = None @@ -27,7 +27,7 @@ class VendorPricing2(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["percent_of_media"] + model: Literal["percent_of_media"] = "percent_of_media" percent: Annotated[ float, Field(description="Percentage of media spend, e.g. 15 = 15%", ge=0.0, le=100.0) ] @@ -56,7 +56,7 @@ class VendorPricing3(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["flat_fee"] + model: Literal["flat_fee"] = "flat_fee" amount: Annotated[float, Field(description="Fixed charge for the billing period", ge=0.0)] period: Annotated[Period, Field(description="Billing period for the flat fee.")] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] @@ -67,7 +67,7 @@ class VendorPricing4(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["per_unit"] + model: Literal["per_unit"] = "per_unit" unit: Annotated[ str, Field( @@ -96,7 +96,7 @@ class VendorPricing5(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["custom"] + model: Literal["custom"] = "custom" description: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/core/signal_pricing_option.py b/src/adcp/types/generated_poc/core/signal_pricing_option.py index 8d09b9ce9..8e149c25d 100644 --- a/src/adcp/types/generated_poc/core/signal_pricing_option.py +++ b/src/adcp/types/generated_poc/core/signal_pricing_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/signal_pricing_option.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/signal_targeting.py b/src/adcp/types/generated_poc/core/signal_targeting.py index d3d6a19f0..56a78a811 100644 --- a/src/adcp/types/generated_poc/core/signal_targeting.py +++ b/src/adcp/types/generated_poc/core/signal_targeting.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/signal_targeting.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -17,7 +17,9 @@ class SignalTargeting4(AdCPBaseModel): extra="allow", ) signal_id: Annotated[signal_id_1.SignalId, Field(description="The signal to target")] - value_type: Annotated[Literal["binary"], Field(description="Discriminator for binary signals")] + value_type: Annotated[ + Literal["binary"], Field(description="Discriminator for binary signals") + ] = "binary" value: Annotated[ bool, Field( @@ -33,7 +35,7 @@ class SignalTargeting5(AdCPBaseModel): signal_id: Annotated[signal_id_1.SignalId, Field(description="The signal to target")] value_type: Annotated[ Literal["categorical"], Field(description="Discriminator for categorical signals") - ] + ] = "categorical" values: Annotated[ list[str], Field( @@ -50,7 +52,7 @@ class SignalTargeting6(AdCPBaseModel): signal_id: Annotated[signal_id_1.SignalId, Field(description="The signal to target")] value_type: Annotated[ Literal["numeric"], Field(description="Discriminator for numeric signals") - ] + ] = "numeric" min_value: Annotated[ float | None, Field( diff --git a/src/adcp/types/generated_poc/core/special.py b/src/adcp/types/generated_poc/core/special.py index 79fefd604..bafdb9c25 100644 --- a/src/adcp/types/generated_poc/core/special.py +++ b/src/adcp/types/generated_poc/core/special.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/special.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/start_timing.py b/src/adcp/types/generated_poc/core/start_timing.py index 1b3dc4030..336b46710 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/store_item.py b/src/adcp/types/generated_poc/core/store_item.py index fe0874012..7fa10d4e5 100644 --- a/src/adcp/types/generated_poc/core/store_item.py +++ b/src/adcp/types/generated_poc/core/store_item.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/store_item.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/talent.py b/src/adcp/types/generated_poc/core/talent.py index 634709c82..85bfdce50 100644 --- a/src/adcp/types/generated_poc/core/talent.py +++ b/src/adcp/types/generated_poc/core/talent.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/talent.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/targeting.py b/src/adcp/types/generated_poc/core/targeting.py index 6d74c5e14..90aee8517 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-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/tasks_get_request.py b/src/adcp/types/generated_poc/core/tasks_get_request.py index ee5d2e82b..59e420100 100644 --- a/src/adcp/types/generated_poc/core/tasks_get_request.py +++ b/src/adcp/types/generated_poc/core/tasks_get_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/tasks_get_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/tasks_get_response.py b/src/adcp/types/generated_poc/core/tasks_get_response.py index 90b6f8d50..25b2074f7 100644 --- a/src/adcp/types/generated_poc/core/tasks_get_response.py +++ b/src/adcp/types/generated_poc/core/tasks_get_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/tasks_get_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/tasks_list_request.py b/src/adcp/types/generated_poc/core/tasks_list_request.py index ea1a8fb79..5e0dd76cd 100644 --- a/src/adcp/types/generated_poc/core/tasks_list_request.py +++ b/src/adcp/types/generated_poc/core/tasks_list_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/tasks_list_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/tasks_list_response.py b/src/adcp/types/generated_poc/core/tasks_list_response.py index eeab182b7..097df5017 100644 --- a/src/adcp/types/generated_poc/core/tasks_list_response.py +++ b/src/adcp/types/generated_poc/core/tasks_list_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/tasks_list_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/user_match.py b/src/adcp/types/generated_poc/core/user_match.py index 451346510..18f2bbb32 100644 --- a/src/adcp/types/generated_poc/core/user_match.py +++ b/src/adcp/types/generated_poc/core/user_match.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/user_match.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/vehicle_item.py b/src/adcp/types/generated_poc/core/vehicle_item.py index 4df23fbc3..65a808266 100644 --- a/src/adcp/types/generated_poc/core/vehicle_item.py +++ b/src/adcp/types/generated_poc/core/vehicle_item.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/vehicle_item.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/core/vendor_pricing_option.py b/src/adcp/types/generated_poc/core/vendor_pricing_option.py index 57d5a56f4..55e3a2be5 100644 --- a/src/adcp/types/generated_poc/core/vendor_pricing_option.py +++ b/src/adcp/types/generated_poc/core/vendor_pricing_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/vendor_pricing_option.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class VendorPricingOption1(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["cpm"] + model: Literal["cpm"] = "cpm" cpm: Annotated[float, Field(description="Cost per thousand impressions", ge=0.0)] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] ext: ext_1.ExtensionObject | None = None @@ -27,7 +27,7 @@ class VendorPricingOption2(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["percent_of_media"] + model: Literal["percent_of_media"] = "percent_of_media" percent: Annotated[ float, Field(description="Percentage of media spend, e.g. 15 = 15%", ge=0.0, le=100.0) ] @@ -56,7 +56,7 @@ class VendorPricingOption3(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["flat_fee"] + model: Literal["flat_fee"] = "flat_fee" amount: Annotated[float, Field(description="Fixed charge for the billing period", ge=0.0)] period: Annotated[Period, Field(description="Billing period for the flat fee.")] currency: Annotated[str, Field(description="ISO 4217 currency code", pattern="^[A-Z]{3}$")] @@ -67,7 +67,7 @@ class VendorPricingOption4(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["per_unit"] + model: Literal["per_unit"] = "per_unit" unit: Annotated[ str, Field( @@ -96,7 +96,7 @@ class VendorPricingOption5(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - model: Literal["custom"] + model: Literal["custom"] = "custom" description: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/core/x_entity_types.py b/src/adcp/types/generated_poc/core/x_entity_types.py index 4210d76d8..6777ff650 100644 --- a/src/adcp/types/generated_poc/core/x_entity_types.py +++ b/src/adcp/types/generated_poc/core/x_entity_types.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/x_entity_types.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/creative/creative_feature_result.py b/src/adcp/types/generated_poc/creative/creative_feature_result.py index 4e841d0fd..ac2d35534 100644 --- a/src/adcp/types/generated_poc/creative/creative_feature_result.py +++ b/src/adcp/types/generated_poc/creative/creative_feature_result.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/creative_feature_result.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/creative/get_creative_delivery_request.py b/src/adcp/types/generated_poc/creative/get_creative_delivery_request.py index f81bf554c..0445d3a86 100644 --- a/src/adcp/types/generated_poc/creative/get_creative_delivery_request.py +++ b/src/adcp/types/generated_poc/creative/get_creative_delivery_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/get_creative_delivery_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/creative/get_creative_delivery_response.py b/src/adcp/types/generated_poc/creative/get_creative_delivery_response.py index 6765c141e..c68256e56 100644 --- a/src/adcp/types/generated_poc/creative/get_creative_delivery_response.py +++ b/src/adcp/types/generated_poc/creative/get_creative_delivery_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/get_creative_delivery_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/creative/get_creative_features_request.py b/src/adcp/types/generated_poc/creative/get_creative_features_request.py index 812bee2c2..2b5b7702c 100644 --- a/src/adcp/types/generated_poc/creative/get_creative_features_request.py +++ b/src/adcp/types/generated_poc/creative/get_creative_features_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/get_creative_features_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/creative/get_creative_features_response.py b/src/adcp/types/generated_poc/creative/get_creative_features_response.py index bfa63397c..44c9be88c 100644 --- a/src/adcp/types/generated_poc/creative/get_creative_features_response.py +++ b/src/adcp/types/generated_poc/creative/get_creative_features_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/get_creative_features_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 21049435b..0fa2f7b0a 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 664b09cd2..8e6558267 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/creative/list_creatives_request.py b/src/adcp/types/generated_poc/creative/list_creatives_request.py index 368f9e257..4fc10015a 100644 --- a/src/adcp/types/generated_poc/creative/list_creatives_request.py +++ b/src/adcp/types/generated_poc/creative/list_creatives_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/list_creatives_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/creative/list_creatives_response.py b/src/adcp/types/generated_poc/creative/list_creatives_response.py index a95b62066..e9278690d 100644 --- a/src/adcp/types/generated_poc/creative/list_creatives_response.py +++ b/src/adcp/types/generated_poc/creative/list_creatives_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/list_creatives_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -167,7 +167,9 @@ class Creative(AdCPBaseModel): | catalog_asset.CatalogAsset, ] | None, - Field(description="Assets for this creative, keyed by asset_id"), + Field( + description="Assets for this creative, keyed by asset_id. Each asset value carries an `asset_type` discriminator that selects the matching asset schema." + ), ] = None tags: Annotated[ list[str] | None, Field(description="User-defined tags for organization and searchability") 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 153f97844..84ae0dda5 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 d2b9bb7c7..80b88228e 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -55,7 +55,7 @@ class PreviewCreativeResponse1(AdCPBaseModel): response_type: Annotated[ Literal["single"], Field(description="Discriminator indicating this is a single preview response"), - ] + ] = "single" previews: Annotated[ list[Preview], Field( @@ -141,7 +141,7 @@ class PreviewCreativeResponse2(AdCPBaseModel): response_type: Annotated[ Literal["batch"], Field(description="Discriminator indicating this is a batch preview response"), - ] + ] = "batch" results: Annotated[ list[Results | Results1], Field( @@ -168,7 +168,7 @@ class PreviewCreativeResponse3(AdCPBaseModel): response_type: Annotated[ Literal["variant"], Field(description="Discriminator indicating this is a variant preview response"), - ] + ] = "variant" variant_id: Annotated[str, Field(description="Platform-assigned variant identifier")] creative_id: Annotated[ str | None, Field(description="Creative identifier this variant belongs to") diff --git a/src/adcp/types/generated_poc/creative/preview_render.py b/src/adcp/types/generated_poc/creative/preview_render.py index ee7d887e6..bf5f74888 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -42,7 +42,7 @@ class PreviewRender1(AdCPBaseModel): ] output_format: Annotated[ Literal["url"], Field(description="Discriminator indicating preview_url is provided") - ] + ] = "url" preview_url: Annotated[ AnyUrl, Field( @@ -73,7 +73,7 @@ class PreviewRender2(AdCPBaseModel): ] output_format: Annotated[ Literal["html"], Field(description="Discriminator indicating preview_html is provided") - ] + ] = "html" preview_html: Annotated[ str, Field( @@ -106,7 +106,7 @@ class PreviewRender3(AdCPBaseModel): Field( description="Discriminator indicating both preview_url and preview_html are provided" ), - ] + ] = "both" preview_url: Annotated[ AnyUrl, Field( diff --git a/src/adcp/types/generated_poc/creative/sync_creatives_async_response_input_required.py b/src/adcp/types/generated_poc/creative/sync_creatives_async_response_input_required.py index 45692c73e..34baae213 100644 --- a/src/adcp/types/generated_poc/creative/sync_creatives_async_response_input_required.py +++ b/src/adcp/types/generated_poc/creative/sync_creatives_async_response_input_required.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/sync_creatives_async_response_input_required.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/creative/sync_creatives_async_response_submitted.py b/src/adcp/types/generated_poc/creative/sync_creatives_async_response_submitted.py index 02a3b3d28..6ce922ea4 100644 --- a/src/adcp/types/generated_poc/creative/sync_creatives_async_response_submitted.py +++ b/src/adcp/types/generated_poc/creative/sync_creatives_async_response_submitted.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/sync_creatives_async_response_submitted.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/creative/sync_creatives_async_response_working.py b/src/adcp/types/generated_poc/creative/sync_creatives_async_response_working.py index f5b46c30d..733e38f56 100644 --- a/src/adcp/types/generated_poc/creative/sync_creatives_async_response_working.py +++ b/src/adcp/types/generated_poc/creative/sync_creatives_async_response_working.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/sync_creatives_async_response_working.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/creative/sync_creatives_request.py b/src/adcp/types/generated_poc/creative/sync_creatives_request.py index b0291230f..cd86baeda 100644 --- a/src/adcp/types/generated_poc/creative/sync_creatives_request.py +++ b/src/adcp/types/generated_poc/creative/sync_creatives_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/sync_creatives_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/creative/sync_creatives_response.py b/src/adcp/types/generated_poc/creative/sync_creatives_response.py index a21ba8e0a..d8d0563e6 100644 --- a/src/adcp/types/generated_poc/creative/sync_creatives_response.py +++ b/src/adcp/types/generated_poc/creative/sync_creatives_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: creative/sync_creatives_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -40,7 +40,7 @@ class SyncCreativesResponse3(AdCPBaseModel): Field( description="Task-level status literal. Discriminates this async envelope from the synchronous success shape, whose creatives array carries per-item approval state via CreativeStatus. See task-status.json for the full task-status enum." ), - ] + ] = "submitted" task_id: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/enums/account_status.py b/src/adcp/types/generated_poc/enums/account_status.py index 9a6b728ba..2f87b477c 100644 --- a/src/adcp/types/generated_poc/enums/account_status.py +++ b/src/adcp/types/generated_poc/enums/account_status.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/account_status.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/action_source.py b/src/adcp/types/generated_poc/enums/action_source.py index d07687e3a..76684c12c 100644 --- a/src/adcp/types/generated_poc/enums/action_source.py +++ b/src/adcp/types/generated_poc/enums/action_source.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/action_source.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/adcp_protocol.py b/src/adcp/types/generated_poc/enums/adcp_protocol.py index 9fc5dc72a..651654208 100644 --- a/src/adcp/types/generated_poc/enums/adcp_protocol.py +++ b/src/adcp/types/generated_poc/enums/adcp_protocol.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/adcp_protocol.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/adjustment_kind.py b/src/adcp/types/generated_poc/enums/adjustment_kind.py index 84226a09d..9022109cc 100644 --- a/src/adcp/types/generated_poc/enums/adjustment_kind.py +++ b/src/adcp/types/generated_poc/enums/adjustment_kind.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/adjustment_kind.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/advertiser_industry.py b/src/adcp/types/generated_poc/enums/advertiser_industry.py index 2d0f7dc69..8a8de9c1d 100644 --- a/src/adcp/types/generated_poc/enums/advertiser_industry.py +++ b/src/adcp/types/generated_poc/enums/advertiser_industry.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/advertiser_industry.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/age_verification_method.py b/src/adcp/types/generated_poc/enums/age_verification_method.py index e662d3aef..e32c0281f 100644 --- a/src/adcp/types/generated_poc/enums/age_verification_method.py +++ b/src/adcp/types/generated_poc/enums/age_verification_method.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/age_verification_method.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/assessment_status.py b/src/adcp/types/generated_poc/enums/assessment_status.py index d4038780a..d5f587a30 100644 --- a/src/adcp/types/generated_poc/enums/assessment_status.py +++ b/src/adcp/types/generated_poc/enums/assessment_status.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/assessment_status.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 fc5500841..e272418bc 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: 2026-02-28T17:39:50+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/attribution_model.py b/src/adcp/types/generated_poc/enums/attribution_model.py index fbacf0865..9e156e1b7 100644 --- a/src/adcp/types/generated_poc/enums/attribution_model.py +++ b/src/adcp/types/generated_poc/enums/attribution_model.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/attribution_model.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/audience_source.py b/src/adcp/types/generated_poc/enums/audience_source.py index 5308c6176..0b5ed7f44 100644 --- a/src/adcp/types/generated_poc/enums/audience_source.py +++ b/src/adcp/types/generated_poc/enums/audience_source.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/audience_source.json -# timestamp: 2026-02-28T17:39:50+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/auth_scheme.py b/src/adcp/types/generated_poc/enums/auth_scheme.py index d00e3d10b..aac448fbc 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/available_metric.py b/src/adcp/types/generated_poc/enums/available_metric.py index 87989e110..1e3c14fbd 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/brand_agent_type.py b/src/adcp/types/generated_poc/enums/brand_agent_type.py index 5022ab375..7aa524e23 100644 --- a/src/adcp/types/generated_poc/enums/brand_agent_type.py +++ b/src/adcp/types/generated_poc/enums/brand_agent_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/brand_agent_type.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/canceled_by.py b/src/adcp/types/generated_poc/enums/canceled_by.py index a3a1f316e..458b5266d 100644 --- a/src/adcp/types/generated_poc/enums/canceled_by.py +++ b/src/adcp/types/generated_poc/enums/canceled_by.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/canceled_by.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/catalog_action.py b/src/adcp/types/generated_poc/enums/catalog_action.py index f57150544..bd8743164 100644 --- a/src/adcp/types/generated_poc/enums/catalog_action.py +++ b/src/adcp/types/generated_poc/enums/catalog_action.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/catalog_action.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/catalog_item_status.py b/src/adcp/types/generated_poc/enums/catalog_item_status.py index fae12d128..e2781ae9f 100644 --- a/src/adcp/types/generated_poc/enums/catalog_item_status.py +++ b/src/adcp/types/generated_poc/enums/catalog_item_status.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/catalog_item_status.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/catalog_type.py b/src/adcp/types/generated_poc/enums/catalog_type.py index 8ba683388..bf06c8f8a 100644 --- a/src/adcp/types/generated_poc/enums/catalog_type.py +++ b/src/adcp/types/generated_poc/enums/catalog_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/catalog_type.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/channels.py b/src/adcp/types/generated_poc/enums/channels.py index 9094c0358..f13aa96cc 100644 --- a/src/adcp/types/generated_poc/enums/channels.py +++ b/src/adcp/types/generated_poc/enums/channels.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/channels.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/cloud_storage_protocol.py b/src/adcp/types/generated_poc/enums/cloud_storage_protocol.py index ed4017b95..2bb6ce73a 100644 --- a/src/adcp/types/generated_poc/enums/cloud_storage_protocol.py +++ b/src/adcp/types/generated_poc/enums/cloud_storage_protocol.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/cloud_storage_protocol.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 70f5a7bd4..cfd7e85ea 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/collection_cadence.py b/src/adcp/types/generated_poc/enums/collection_cadence.py index eeea5bbe4..68d7055ee 100644 --- a/src/adcp/types/generated_poc/enums/collection_cadence.py +++ b/src/adcp/types/generated_poc/enums/collection_cadence.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/collection_cadence.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/collection_relationship.py b/src/adcp/types/generated_poc/enums/collection_relationship.py index 7da673490..744ecb3b2 100644 --- a/src/adcp/types/generated_poc/enums/collection_relationship.py +++ b/src/adcp/types/generated_poc/enums/collection_relationship.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/collection_relationship.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/collection_status.py b/src/adcp/types/generated_poc/enums/collection_status.py index 74e0151cf..449771e68 100644 --- a/src/adcp/types/generated_poc/enums/collection_status.py +++ b/src/adcp/types/generated_poc/enums/collection_status.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/collection_status.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/consent_basis.py b/src/adcp/types/generated_poc/enums/consent_basis.py index e967d19df..102dea56c 100644 --- a/src/adcp/types/generated_poc/enums/consent_basis.py +++ b/src/adcp/types/generated_poc/enums/consent_basis.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/consent_basis.json -# timestamp: 2026-02-28T17:39:50+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/content_id_type.py b/src/adcp/types/generated_poc/enums/content_id_type.py index 39ac3fb88..08d31215d 100644 --- a/src/adcp/types/generated_poc/enums/content_id_type.py +++ b/src/adcp/types/generated_poc/enums/content_id_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/content_id_type.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/content_rating_system.py b/src/adcp/types/generated_poc/enums/content_rating_system.py index de6c83b02..4df6ca523 100644 --- a/src/adcp/types/generated_poc/enums/content_rating_system.py +++ b/src/adcp/types/generated_poc/enums/content_rating_system.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/content_rating_system.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/creative_action.py b/src/adcp/types/generated_poc/enums/creative_action.py index c39510906..8ee3047e3 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 dd6296b50..3d18e05fe 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/creative_approval_status.py b/src/adcp/types/generated_poc/enums/creative_approval_status.py index 759ab22cd..69ba76d43 100644 --- a/src/adcp/types/generated_poc/enums/creative_approval_status.py +++ b/src/adcp/types/generated_poc/enums/creative_approval_status.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/creative_approval_status.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/creative_identifier_type.py b/src/adcp/types/generated_poc/enums/creative_identifier_type.py index 2a76d707b..1d869a080 100644 --- a/src/adcp/types/generated_poc/enums/creative_identifier_type.py +++ b/src/adcp/types/generated_poc/enums/creative_identifier_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/creative_identifier_type.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/creative_quality.py b/src/adcp/types/generated_poc/enums/creative_quality.py index 495992740..adf4aa28a 100644 --- a/src/adcp/types/generated_poc/enums/creative_quality.py +++ b/src/adcp/types/generated_poc/enums/creative_quality.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/creative_quality.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 2c1233e41..844bec27a 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: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/creative_status.py b/src/adcp/types/generated_poc/enums/creative_status.py index c3f3d1600..e07ad4a7a 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: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 aa0b56474..a9f3a4115 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: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/daast_version.py b/src/adcp/types/generated_poc/enums/daast_version.py index 94ff7cebc..b40aa4e40 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/day_of_week.py b/src/adcp/types/generated_poc/enums/day_of_week.py index 5c520a2e3..ddb04245a 100644 --- a/src/adcp/types/generated_poc/enums/day_of_week.py +++ b/src/adcp/types/generated_poc/enums/day_of_week.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/day_of_week.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/delegation_authority.py b/src/adcp/types/generated_poc/enums/delegation_authority.py index a343d24a8..0adfaefed 100644 --- a/src/adcp/types/generated_poc/enums/delegation_authority.py +++ b/src/adcp/types/generated_poc/enums/delegation_authority.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/delegation_authority.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/delivery_type.py b/src/adcp/types/generated_poc/enums/delivery_type.py index aa8cecf6c..8633ed4d7 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/demographic_system.py b/src/adcp/types/generated_poc/enums/demographic_system.py index 8d1c05a4a..82de4fac8 100644 --- a/src/adcp/types/generated_poc/enums/demographic_system.py +++ b/src/adcp/types/generated_poc/enums/demographic_system.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/demographic_system.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/derivative_type.py b/src/adcp/types/generated_poc/enums/derivative_type.py index 3e3969a2e..e18269267 100644 --- a/src/adcp/types/generated_poc/enums/derivative_type.py +++ b/src/adcp/types/generated_poc/enums/derivative_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/derivative_type.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/device_platform.py b/src/adcp/types/generated_poc/enums/device_platform.py index 41a9681e2..fac6b0ef4 100644 --- a/src/adcp/types/generated_poc/enums/device_platform.py +++ b/src/adcp/types/generated_poc/enums/device_platform.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/device_platform.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/device_type.py b/src/adcp/types/generated_poc/enums/device_type.py index 1d30445be..536b36204 100644 --- a/src/adcp/types/generated_poc/enums/device_type.py +++ b/src/adcp/types/generated_poc/enums/device_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/device_type.json -# timestamp: 2026-02-28T17:39:50+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/digital_source_type.py b/src/adcp/types/generated_poc/enums/digital_source_type.py index 98a6726b2..2b75fe492 100644 --- a/src/adcp/types/generated_poc/enums/digital_source_type.py +++ b/src/adcp/types/generated_poc/enums/digital_source_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/digital_source_type.json -# timestamp: 2026-02-28T17:39:50+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/dimension_unit.py b/src/adcp/types/generated_poc/enums/dimension_unit.py index 7ce62280a..c5cf6410f 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: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/disclosure_persistence.py b/src/adcp/types/generated_poc/enums/disclosure_persistence.py index e29098747..3a5d7a809 100644 --- a/src/adcp/types/generated_poc/enums/disclosure_persistence.py +++ b/src/adcp/types/generated_poc/enums/disclosure_persistence.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/disclosure_persistence.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/disclosure_position.py b/src/adcp/types/generated_poc/enums/disclosure_position.py index 1afaa4cdc..3c625be51 100644 --- a/src/adcp/types/generated_poc/enums/disclosure_position.py +++ b/src/adcp/types/generated_poc/enums/disclosure_position.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/disclosure_position.json -# timestamp: 2026-02-28T17:39:50+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/distance_unit.py b/src/adcp/types/generated_poc/enums/distance_unit.py index e7da9e128..2c7214cec 100644 --- a/src/adcp/types/generated_poc/enums/distance_unit.py +++ b/src/adcp/types/generated_poc/enums/distance_unit.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/distance_unit.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/distribution_identifier_type.py b/src/adcp/types/generated_poc/enums/distribution_identifier_type.py index 69f321709..875b6b730 100644 --- a/src/adcp/types/generated_poc/enums/distribution_identifier_type.py +++ b/src/adcp/types/generated_poc/enums/distribution_identifier_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/distribution_identifier_type.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/error_code.py b/src/adcp/types/generated_poc/enums/error_code.py index 288772dca..1aca29e21 100644 --- a/src/adcp/types/generated_poc/enums/error_code.py +++ b/src/adcp/types/generated_poc/enums/error_code.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/error_code.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/escalation_severity.py b/src/adcp/types/generated_poc/enums/escalation_severity.py index 53b13b83c..a5652c31a 100644 --- a/src/adcp/types/generated_poc/enums/escalation_severity.py +++ b/src/adcp/types/generated_poc/enums/escalation_severity.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/escalation_severity.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/event_type.py b/src/adcp/types/generated_poc/enums/event_type.py index 82b99cd30..a78650529 100644 --- a/src/adcp/types/generated_poc/enums/event_type.py +++ b/src/adcp/types/generated_poc/enums/event_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/event_type.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/exclusivity.py b/src/adcp/types/generated_poc/enums/exclusivity.py index b305ca964..cc3546b28 100644 --- a/src/adcp/types/generated_poc/enums/exclusivity.py +++ b/src/adcp/types/generated_poc/enums/exclusivity.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/exclusivity.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/feed_format.py b/src/adcp/types/generated_poc/enums/feed_format.py index ad284ca5c..3003d53b2 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/feedback_source.py b/src/adcp/types/generated_poc/enums/feedback_source.py index 8181ac43d..1b73e4034 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/forecast_method.py b/src/adcp/types/generated_poc/enums/forecast_method.py index 007f8a5d1..de20ee349 100644 --- a/src/adcp/types/generated_poc/enums/forecast_method.py +++ b/src/adcp/types/generated_poc/enums/forecast_method.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/forecast_method.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/forecast_range_unit.py b/src/adcp/types/generated_poc/enums/forecast_range_unit.py index 6d7b84057..d82f15e0e 100644 --- a/src/adcp/types/generated_poc/enums/forecast_range_unit.py +++ b/src/adcp/types/generated_poc/enums/forecast_range_unit.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/forecast_range_unit.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/forecastable_metric.py b/src/adcp/types/generated_poc/enums/forecastable_metric.py index 1309ec474..8613e4b2a 100644 --- a/src/adcp/types/generated_poc/enums/forecastable_metric.py +++ b/src/adcp/types/generated_poc/enums/forecastable_metric.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/forecastable_metric.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 60dee5a89..90cd06342 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 1e3de7be3..66292315e 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -13,4 +13,4 @@ class FrequencyCapScope(RootModel[Literal["package"]]): root: Annotated[ Literal["package"], Field(description="Scope for frequency cap application", title="Frequency Cap Scope"), - ] + ] = "package" diff --git a/src/adcp/types/generated_poc/enums/genre_taxonomy.py b/src/adcp/types/generated_poc/enums/genre_taxonomy.py index 027764b90..b8fb0a6ad 100644 --- a/src/adcp/types/generated_poc/enums/genre_taxonomy.py +++ b/src/adcp/types/generated_poc/enums/genre_taxonomy.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/genre_taxonomy.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/geo_level.py b/src/adcp/types/generated_poc/enums/geo_level.py index 50d6797fa..de4fed1c9 100644 --- a/src/adcp/types/generated_poc/enums/geo_level.py +++ b/src/adcp/types/generated_poc/enums/geo_level.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/geo_level.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/governance_domain.py b/src/adcp/types/generated_poc/enums/governance_domain.py index c1c04a2dd..0589e4c36 100644 --- a/src/adcp/types/generated_poc/enums/governance_domain.py +++ b/src/adcp/types/generated_poc/enums/governance_domain.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/governance_domain.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/governance_mode.py b/src/adcp/types/generated_poc/enums/governance_mode.py index 4437cfbf4..5693b6597 100644 --- a/src/adcp/types/generated_poc/enums/governance_mode.py +++ b/src/adcp/types/generated_poc/enums/governance_mode.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/governance_mode.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/governance_phase.py b/src/adcp/types/generated_poc/enums/governance_phase.py index e12bc2e04..130502720 100644 --- a/src/adcp/types/generated_poc/enums/governance_phase.py +++ b/src/adcp/types/generated_poc/enums/governance_phase.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/governance_phase.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 b80c40f8f..fec750f03 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/http_method.py b/src/adcp/types/generated_poc/enums/http_method.py index 725bc47ab..b3d56fae3 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/identifier_types.py b/src/adcp/types/generated_poc/enums/identifier_types.py index ff2d86a2c..6006aa3fc 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: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/installment_status.py b/src/adcp/types/generated_poc/enums/installment_status.py index e7e3f10c5..22c9f1295 100644 --- a/src/adcp/types/generated_poc/enums/installment_status.py +++ b/src/adcp/types/generated_poc/enums/installment_status.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/installment_status.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 055eacf16..a461540f3 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 1c538ee8c..ec1ca6477 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/makegood_remedy.py b/src/adcp/types/generated_poc/enums/makegood_remedy.py index 0f59fc453..91c24c323 100644 --- a/src/adcp/types/generated_poc/enums/makegood_remedy.py +++ b/src/adcp/types/generated_poc/enums/makegood_remedy.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/makegood_remedy.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/markdown_flavor.py b/src/adcp/types/generated_poc/enums/markdown_flavor.py index 65e9a999c..a6c93394f 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/match_id_type.py b/src/adcp/types/generated_poc/enums/match_id_type.py index a595f0e44..7cae33b77 100644 --- a/src/adcp/types/generated_poc/enums/match_id_type.py +++ b/src/adcp/types/generated_poc/enums/match_id_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/match_id_type.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 5bfcc0f3c..91f2df5e3 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: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/metric_type.py b/src/adcp/types/generated_poc/enums/metric_type.py index 478f20693..c28040349 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/metro_system.py b/src/adcp/types/generated_poc/enums/metro_system.py index 6651e0778..9ab67a917 100644 --- a/src/adcp/types/generated_poc/enums/metro_system.py +++ b/src/adcp/types/generated_poc/enums/metro_system.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/metro_system.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/notification_type.py b/src/adcp/types/generated_poc/enums/notification_type.py index c203d2382..ef7592ae7 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/outcome_type.py b/src/adcp/types/generated_poc/enums/outcome_type.py index 14f2bcd84..104026a24 100644 --- a/src/adcp/types/generated_poc/enums/outcome_type.py +++ b/src/adcp/types/generated_poc/enums/outcome_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/outcome_type.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/pacing.py b/src/adcp/types/generated_poc/enums/pacing.py index 41ac206ec..1e2bfc7cb 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/performance_standard_metric.py b/src/adcp/types/generated_poc/enums/performance_standard_metric.py index 6f018fe8b..1e963ff50 100644 --- a/src/adcp/types/generated_poc/enums/performance_standard_metric.py +++ b/src/adcp/types/generated_poc/enums/performance_standard_metric.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/performance_standard_metric.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/policy_category.py b/src/adcp/types/generated_poc/enums/policy_category.py index 5a39718eb..21ad6fce4 100644 --- a/src/adcp/types/generated_poc/enums/policy_category.py +++ b/src/adcp/types/generated_poc/enums/policy_category.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/policy_category.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/policy_enforcement.py b/src/adcp/types/generated_poc/enums/policy_enforcement.py index 03339f7b1..86955bb47 100644 --- a/src/adcp/types/generated_poc/enums/policy_enforcement.py +++ b/src/adcp/types/generated_poc/enums/policy_enforcement.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/policy_enforcement.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/postal_system.py b/src/adcp/types/generated_poc/enums/postal_system.py index b7ee922e0..bfec1d526 100644 --- a/src/adcp/types/generated_poc/enums/postal_system.py +++ b/src/adcp/types/generated_poc/enums/postal_system.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/postal_system.json -# timestamp: 2026-02-27T02:10:10+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 a82682204..b6a9abc1e 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: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/pricing_model.py b/src/adcp/types/generated_poc/enums/pricing_model.py index 3eeb496e4..574a25c8d 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/production_quality.py b/src/adcp/types/generated_poc/enums/production_quality.py index 630f63a53..b83d590f2 100644 --- a/src/adcp/types/generated_poc/enums/production_quality.py +++ b/src/adcp/types/generated_poc/enums/production_quality.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/production_quality.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/property_type.py b/src/adcp/types/generated_poc/enums/property_type.py index 8e82b79c3..0c617f74e 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: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/proposal_status.py b/src/adcp/types/generated_poc/enums/proposal_status.py index 66591c8d8..58274579b 100644 --- a/src/adcp/types/generated_poc/enums/proposal_status.py +++ b/src/adcp/types/generated_poc/enums/proposal_status.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/proposal_status.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 bea011b46..d84c8b3f0 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/purchase_type.py b/src/adcp/types/generated_poc/enums/purchase_type.py index 46403ab93..42f2ecc43 100644 --- a/src/adcp/types/generated_poc/enums/purchase_type.py +++ b/src/adcp/types/generated_poc/enums/purchase_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/purchase_type.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/reach_unit.py b/src/adcp/types/generated_poc/enums/reach_unit.py index 256317114..ed75ece6f 100644 --- a/src/adcp/types/generated_poc/enums/reach_unit.py +++ b/src/adcp/types/generated_poc/enums/reach_unit.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/reach_unit.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/reporting_frequency.py b/src/adcp/types/generated_poc/enums/reporting_frequency.py index 5c954539c..0d68c421b 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/response_type.py b/src/adcp/types/generated_poc/enums/response_type.py index fc0f31ece..c28da1776 100644 --- a/src/adcp/types/generated_poc/enums/response_type.py +++ b/src/adcp/types/generated_poc/enums/response_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/response_type.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/restricted_attribute.py b/src/adcp/types/generated_poc/enums/restricted_attribute.py index 261de2429..7fea6f5ca 100644 --- a/src/adcp/types/generated_poc/enums/restricted_attribute.py +++ b/src/adcp/types/generated_poc/enums/restricted_attribute.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/restricted_attribute.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/right_type.py b/src/adcp/types/generated_poc/enums/right_type.py index 8ebe85638..808ebcffc 100644 --- a/src/adcp/types/generated_poc/enums/right_type.py +++ b/src/adcp/types/generated_poc/enums/right_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/right_type.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/right_use.py b/src/adcp/types/generated_poc/enums/right_use.py index be0b953bc..170ecd5e5 100644 --- a/src/adcp/types/generated_poc/enums/right_use.py +++ b/src/adcp/types/generated_poc/enums/right_use.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/right_use.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/si_session_status.py b/src/adcp/types/generated_poc/enums/si_session_status.py index 09726228a..d284061a2 100644 --- a/src/adcp/types/generated_poc/enums/si_session_status.py +++ b/src/adcp/types/generated_poc/enums/si_session_status.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/si_session_status.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 06552f4f0..40ac5ed73 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/signal_source.py b/src/adcp/types/generated_poc/enums/signal_source.py index 5e00e065a..40225b0e9 100644 --- a/src/adcp/types/generated_poc/enums/signal_source.py +++ b/src/adcp/types/generated_poc/enums/signal_source.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/signal_source.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/signal_value_type.py b/src/adcp/types/generated_poc/enums/signal_value_type.py index fe52d8c78..ca6b27542 100644 --- a/src/adcp/types/generated_poc/enums/signal_value_type.py +++ b/src/adcp/types/generated_poc/enums/signal_value_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/signal_value_type.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/sort_direction.py b/src/adcp/types/generated_poc/enums/sort_direction.py index 27ae0747a..c81964e35 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: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/sort_metric.py b/src/adcp/types/generated_poc/enums/sort_metric.py index 30bf559f4..531761dc4 100644 --- a/src/adcp/types/generated_poc/enums/sort_metric.py +++ b/src/adcp/types/generated_poc/enums/sort_metric.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/sort_metric.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/special_category.py b/src/adcp/types/generated_poc/enums/special_category.py index 5ebc15006..17db72a51 100644 --- a/src/adcp/types/generated_poc/enums/special_category.py +++ b/src/adcp/types/generated_poc/enums/special_category.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/special_category.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/specialism.py b/src/adcp/types/generated_poc/enums/specialism.py index 835ae4430..9d30896d6 100644 --- a/src/adcp/types/generated_poc/enums/specialism.py +++ b/src/adcp/types/generated_poc/enums/specialism.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/specialism.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/talent_role.py b/src/adcp/types/generated_poc/enums/talent_role.py index b8e4bf051..3cf25646f 100644 --- a/src/adcp/types/generated_poc/enums/talent_role.py +++ b/src/adcp/types/generated_poc/enums/talent_role.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/talent_role.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/task_status.py b/src/adcp/types/generated_poc/enums/task_status.py index 917f05dcc..93e58b615 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/task_type.py b/src/adcp/types/generated_poc/enums/task_type.py index 07d4111b9..2d33d798e 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-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/transport_mode.py b/src/adcp/types/generated_poc/enums/transport_mode.py index 2a798863c..535a144a5 100644 --- a/src/adcp/types/generated_poc/enums/transport_mode.py +++ b/src/adcp/types/generated_poc/enums/transport_mode.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/transport_mode.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/uid_type.py b/src/adcp/types/generated_poc/enums/uid_type.py index a900af09b..470a29f2d 100644 --- a/src/adcp/types/generated_poc/enums/uid_type.py +++ b/src/adcp/types/generated_poc/enums/uid_type.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/uid_type.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/universal_macro.py b/src/adcp/types/generated_poc/enums/universal_macro.py index 98e9645e2..554cde7a0 100644 --- a/src/adcp/types/generated_poc/enums/universal_macro.py +++ b/src/adcp/types/generated_poc/enums/universal_macro.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/universal_macro.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/update_frequency.py b/src/adcp/types/generated_poc/enums/update_frequency.py index e6a0b52ea..08ad209c9 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 3391646fe..a0743b5f4 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/validation_mode.py b/src/adcp/types/generated_poc/enums/validation_mode.py index 646eeac43..6af9423d9 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 db656057d..fe85cd8e4 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: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/vast_version.py b/src/adcp/types/generated_poc/enums/vast_version.py index 36b189e01..596c5c52b 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/viewability_standard.py b/src/adcp/types/generated_poc/enums/viewability_standard.py index 77dd47834..2cf6f65a0 100644 --- a/src/adcp/types/generated_poc/enums/viewability_standard.py +++ b/src/adcp/types/generated_poc/enums/viewability_standard.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/viewability_standard.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/enums/wcag_level.py b/src/adcp/types/generated_poc/enums/wcag_level.py index 8d8aa217e..ff440031c 100644 --- a/src/adcp/types/generated_poc/enums/wcag_level.py +++ b/src/adcp/types/generated_poc/enums/wcag_level.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: enums/wcag_level.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 bf0edfd5c..e9ce0477f 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 fdeeb65da..b2f5310a8 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: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/error_details/account_setup_required.py b/src/adcp/types/generated_poc/error_details/account_setup_required.py index 533b7f02d..f07838110 100644 --- a/src/adcp/types/generated_poc/error_details/account_setup_required.py +++ b/src/adcp/types/generated_poc/error_details/account_setup_required.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: error_details/account_setup_required.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/error_details/audience_too_small.py b/src/adcp/types/generated_poc/error_details/audience_too_small.py index be0d446ff..e69c024d6 100644 --- a/src/adcp/types/generated_poc/error_details/audience_too_small.py +++ b/src/adcp/types/generated_poc/error_details/audience_too_small.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: error_details/audience_too_small.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/error_details/budget_too_low.py b/src/adcp/types/generated_poc/error_details/budget_too_low.py index 0e535e27f..4f2b422bf 100644 --- a/src/adcp/types/generated_poc/error_details/budget_too_low.py +++ b/src/adcp/types/generated_poc/error_details/budget_too_low.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: error_details/budget_too_low.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/error_details/conflict.py b/src/adcp/types/generated_poc/error_details/conflict.py index 69bf959bd..0c64672dc 100644 --- a/src/adcp/types/generated_poc/error_details/conflict.py +++ b/src/adcp/types/generated_poc/error_details/conflict.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: error_details/conflict.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/error_details/creative_rejected.py b/src/adcp/types/generated_poc/error_details/creative_rejected.py index e84e1f178..0fac597e5 100644 --- a/src/adcp/types/generated_poc/error_details/creative_rejected.py +++ b/src/adcp/types/generated_poc/error_details/creative_rejected.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: error_details/creative_rejected.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/error_details/policy_violation.py b/src/adcp/types/generated_poc/error_details/policy_violation.py index 8f61e8635..5a3fe8f38 100644 --- a/src/adcp/types/generated_poc/error_details/policy_violation.py +++ b/src/adcp/types/generated_poc/error_details/policy_violation.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: error_details/policy_violation.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/error_details/rate_limited.py b/src/adcp/types/generated_poc/error_details/rate_limited.py index 38b7ce290..2fea68451 100644 --- a/src/adcp/types/generated_poc/error_details/rate_limited.py +++ b/src/adcp/types/generated_poc/error_details/rate_limited.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: error_details/rate_limited.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/error_details/vendor_error_codes.py b/src/adcp/types/generated_poc/error_details/vendor_error_codes.py index bf1a9c0dd..9da101c65 100644 --- a/src/adcp/types/generated_poc/error_details/vendor_error_codes.py +++ b/src/adcp/types/generated_poc/error_details/vendor_error_codes.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: error_details/vendor_error_codes.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/extensions/extension_meta.py b/src/adcp/types/generated_poc/extensions/extension_meta.py index 0b5658761..b4c601163 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-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -13,7 +13,7 @@ class AdcpExtensionFileSchema(AdCPBaseModel): field_schema: Annotated[ Literal["http://json-schema.org/draft-07/schema#"], Field(alias="$schema") - ] + ] = "http://json-schema.org/draft-07/schema#" title: Annotated[str, Field(description="Human-readable title for the extension")] description: Annotated[str, Field(description="Description of what this extension provides")] valid_from: Annotated[ @@ -36,7 +36,7 @@ class AdcpExtensionFileSchema(AdCPBaseModel): type: Annotated[ Literal["object"], Field(description="Extensions must be objects (data within ext.{namespace})"), - ] + ] = "object" properties: Annotated[ dict[str, Any], Field(description="Schema properties defining the structure of ext.{namespace} data"), diff --git a/src/adcp/types/generated_poc/governance/attribute_definition.py b/src/adcp/types/generated_poc/governance/attribute_definition.py index a835daa11..7fd994db5 100644 --- a/src/adcp/types/generated_poc/governance/attribute_definition.py +++ b/src/adcp/types/generated_poc/governance/attribute_definition.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: governance/attribute_definition.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/governance/audience_constraints.py b/src/adcp/types/generated_poc/governance/audience_constraints.py index 33808b340..f47353290 100644 --- a/src/adcp/types/generated_poc/governance/audience_constraints.py +++ b/src/adcp/types/generated_poc/governance/audience_constraints.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: governance/audience_constraints.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/governance/check_governance_request.py b/src/adcp/types/generated_poc/governance/check_governance_request.py index 4c651816a..08f8a1782 100644 --- a/src/adcp/types/generated_poc/governance/check_governance_request.py +++ b/src/adcp/types/generated_poc/governance/check_governance_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: governance/check_governance_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -125,7 +125,12 @@ class CheckGovernanceRequest(AdCPBaseModel): le=99, ), ] = None - plan_id: Annotated[str, Field(description="Campaign governance plan identifier.")] + plan_id: Annotated[ + str, + Field( + description="Campaign governance plan identifier. The plan uniquely scopes the account and operator; do not include a separate `account` field — the governance agent resolves account from the plan. Including `account` is rejected by `additionalProperties: false`." + ), + ] caller: Annotated[AnyUrl, Field(description="URL of the agent making the request.")] purchase_type: Annotated[ purchase_type_1.PurchaseType | None, diff --git a/src/adcp/types/generated_poc/governance/check_governance_response.py b/src/adcp/types/generated_poc/governance/check_governance_response.py index e884ce4c0..c38ca9a58 100644 --- a/src/adcp/types/generated_poc/governance/check_governance_response.py +++ b/src/adcp/types/generated_poc/governance/check_governance_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: governance/check_governance_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/governance/get_plan_audit_logs_request.py b/src/adcp/types/generated_poc/governance/get_plan_audit_logs_request.py index b875fc52f..150363666 100644 --- a/src/adcp/types/generated_poc/governance/get_plan_audit_logs_request.py +++ b/src/adcp/types/generated_poc/governance/get_plan_audit_logs_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: governance/get_plan_audit_logs_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -29,7 +29,7 @@ class GetPlanAuditLogsRequest(AdCPBaseModel): plan_ids: Annotated[ list[str] | None, Field( - description="Plan IDs to retrieve. For a single plan, pass a one-element array.", + description="Plan IDs to retrieve. For a single plan, pass a one-element array. Plans uniquely scope account and operator; do not include a separate `account` field — the governance agent resolves account from each plan. Including `account` is rejected by `additionalProperties: false`.", min_length=1, ), ] = None diff --git a/src/adcp/types/generated_poc/governance/get_plan_audit_logs_response.py b/src/adcp/types/generated_poc/governance/get_plan_audit_logs_response.py index c40bf2966..19525423b 100644 --- a/src/adcp/types/generated_poc/governance/get_plan_audit_logs_response.py +++ b/src/adcp/types/generated_poc/governance/get_plan_audit_logs_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: governance/get_plan_audit_logs_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/governance/policy_category_definition.py b/src/adcp/types/generated_poc/governance/policy_category_definition.py index 4bad40510..9b1e0ec62 100644 --- a/src/adcp/types/generated_poc/governance/policy_category_definition.py +++ b/src/adcp/types/generated_poc/governance/policy_category_definition.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: governance/policy_category_definition.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/governance/policy_entry.py b/src/adcp/types/generated_poc/governance/policy_entry.py index cf067746c..5be8d6476 100644 --- a/src/adcp/types/generated_poc/governance/policy_entry.py +++ b/src/adcp/types/generated_poc/governance/policy_entry.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: governance/policy_entry.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/governance/policy_ref.py b/src/adcp/types/generated_poc/governance/policy_ref.py index b5ceb3cdb..707e6d291 100644 --- a/src/adcp/types/generated_poc/governance/policy_ref.py +++ b/src/adcp/types/generated_poc/governance/policy_ref.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: governance/policy_ref.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/governance/report_plan_outcome_request.py b/src/adcp/types/generated_poc/governance/report_plan_outcome_request.py index e09337b9a..2b429eea5 100644 --- a/src/adcp/types/generated_poc/governance/report_plan_outcome_request.py +++ b/src/adcp/types/generated_poc/governance/report_plan_outcome_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: governance/report_plan_outcome_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -103,7 +103,12 @@ class ReportPlanOutcomeRequest(AdCPBaseModel): le=99, ), ] = None - plan_id: Annotated[str, Field(description="The plan this outcome is for.")] + plan_id: Annotated[ + str, + Field( + description="The plan this outcome is for. The plan uniquely scopes the account and operator; do not include a separate `account` field — the governance agent resolves account from the plan. Including `account` is rejected by `additionalProperties: false`." + ), + ] check_id: Annotated[ str | None, Field( diff --git a/src/adcp/types/generated_poc/governance/report_plan_outcome_response.py b/src/adcp/types/generated_poc/governance/report_plan_outcome_response.py index 802dc64a7..e9bca4c7e 100644 --- a/src/adcp/types/generated_poc/governance/report_plan_outcome_response.py +++ b/src/adcp/types/generated_poc/governance/report_plan_outcome_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: governance/report_plan_outcome_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/governance/sync_plans_request.py b/src/adcp/types/generated_poc/governance/sync_plans_request.py index 1b8bcc09e..d1d21a39f 100644 --- a/src/adcp/types/generated_poc/governance/sync_plans_request.py +++ b/src/adcp/types/generated_poc/governance/sync_plans_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: governance/sync_plans_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/governance/sync_plans_response.py b/src/adcp/types/generated_poc/governance/sync_plans_response.py index 92b55205b..9cfdef89f 100644 --- a/src/adcp/types/generated_poc/governance/sync_plans_response.py +++ b/src/adcp/types/generated_poc/governance/sync_plans_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: governance/sync_plans_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -20,7 +20,7 @@ class Status(Enum): error = "error" -class Status38(Enum): +class Status42(Enum): active = "active" inactive = "inactive" @@ -30,7 +30,7 @@ class Category(AdCPBaseModel): extra="forbid", ) category_id: Annotated[str, Field(description="Validation category identifier.")] - status: Annotated[Status38, Field(description="Whether this category is active for this plan.")] + status: Annotated[Status42, Field(description="Whether this category is active for this plan.")] class Source(Enum): diff --git a/src/adcp/types/generated_poc/media_buy/build_creative_async_response_input_required.py b/src/adcp/types/generated_poc/media_buy/build_creative_async_response_input_required.py index ef2a65018..810e4d7a2 100644 --- a/src/adcp/types/generated_poc/media_buy/build_creative_async_response_input_required.py +++ b/src/adcp/types/generated_poc/media_buy/build_creative_async_response_input_required.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/build_creative_async_response_input_required.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/build_creative_async_response_submitted.py b/src/adcp/types/generated_poc/media_buy/build_creative_async_response_submitted.py index 68c1ddc10..1c785e740 100644 --- a/src/adcp/types/generated_poc/media_buy/build_creative_async_response_submitted.py +++ b/src/adcp/types/generated_poc/media_buy/build_creative_async_response_submitted.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/build_creative_async_response_submitted.json -# timestamp: 2026-03-16T00:33:16+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/build_creative_async_response_working.py b/src/adcp/types/generated_poc/media_buy/build_creative_async_response_working.py index 2faaa5703..b7c57360f 100644 --- a/src/adcp/types/generated_poc/media_buy/build_creative_async_response_working.py +++ b/src/adcp/types/generated_poc/media_buy/build_creative_async_response_working.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/build_creative_async_response_working.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 22555f780..9de8e617b 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 6c0951ef1..5ea7e8a80 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 e8853ad55..262922f11 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-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 dac799ecf..4386bc668 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-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 2f8baf086..1a2d57d24 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-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 8fc4293eb..3a41ac300 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 7ef08fc7f..1518219f4 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-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -52,7 +52,7 @@ class CreateMediaBuyResponse3(AdCPBaseModel): Field( description="Task-level status literal. Discriminates this async envelope from the synchronous success shape, whose status field carries a MediaBuyStatus value (pending_creatives, pending_start, active). See task-status.json for the full task-status enum." ), - ] + ] = "submitted" task_id: Annotated[ str, Field( 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 cc5cf302c..3ba00d6a7 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 ac1e97ca7..f24bd381a 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/get_media_buys_request.py b/src/adcp/types/generated_poc/media_buy/get_media_buys_request.py index 4174d9eb3..d19064f0e 100644 --- a/src/adcp/types/generated_poc/media_buy/get_media_buys_request.py +++ b/src/adcp/types/generated_poc/media_buy/get_media_buys_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_media_buys_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/get_media_buys_response.py b/src/adcp/types/generated_poc/media_buy/get_media_buys_response.py index 04e865acc..a17634008 100644 --- a/src/adcp/types/generated_poc/media_buy/get_media_buys_response.py +++ b/src/adcp/types/generated_poc/media_buy/get_media_buys_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_media_buys_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 23c633379..102929752 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-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 df425d28d..28f9cba29 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-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 72ece5a42..8af4b616d 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-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 9b25771fa..81295ad9c 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,14 +1,14 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations from enum import Enum -from typing import Annotated, Literal +from typing import Any, Annotated, Literal from adcp.types.base import AdCPBaseModel -from pydantic import ConfigDict, Field +from pydantic import ConfigDict, Field, RootModel from ..core import account_ref, brand_ref from ..core import catalog as catalog_1 @@ -25,7 +25,7 @@ class BuyingMode(Enum): refine = "refine" -class Refine(AdCPBaseModel): +class Refine1(AdCPBaseModel): model_config = ConfigDict( extra="forbid", ) @@ -34,7 +34,7 @@ class Refine(AdCPBaseModel): Field( description="Change scoped to the overall request — direction for the selection as a whole." ), - ] + ] = "request" ask: Annotated[ str, Field( @@ -50,20 +50,22 @@ class Action(Enum): more_like_this = "more_like_this" -class Refine1(AdCPBaseModel): +class Refine2(AdCPBaseModel): model_config = ConfigDict( extra="forbid", ) - scope: Annotated[Literal["product"], Field(description="Change scoped to a specific product.")] - id: Annotated[ + scope: Annotated[ + Literal["product"], Field(description="Change scoped to a specific product.") + ] = "product" + product_id: Annotated[ str, Field(description="Product ID from a previous get_products response.", min_length=1) ] action: Annotated[ - Action, + Action | None, Field( - description="'include': return this product with updated pricing and data. 'omit': exclude this product from the response. 'more_like_this': find additional products similar to this one (the original is also returned)." + description="'include' (default): return this product with updated pricing and data. 'omit': exclude this product from the response. 'more_like_this': find additional products similar to this one (the original is also returned). Optional — when omitted, the seller treats the entry as action: 'include'." ), - ] + ] = Action.include ask: Annotated[ str | None, Field( @@ -79,22 +81,22 @@ class Action3(Enum): finalize = "finalize" -class Refine2(AdCPBaseModel): +class Refine3(AdCPBaseModel): model_config = ConfigDict( extra="forbid", ) scope: Annotated[ Literal["proposal"], Field(description="Change scoped to a specific proposal.") - ] - id: Annotated[ + ] = "proposal" + proposal_id: Annotated[ str, Field(description="Proposal ID from a previous get_products response.", min_length=1) ] action: Annotated[ - Action3, + Action3 | None, Field( - description="'include': return this proposal with updated allocations and pricing. 'omit': exclude this proposal from the response. 'finalize': request firm pricing and inventory hold — transitions a draft proposal to committed with an expires_at hold window. May trigger seller-side approval (HITL). The buyer should not set a time_budget for finalize requests — they represent a commitment to wait for the result." + description="'include' (default): return this proposal with updated allocations and pricing. 'omit': exclude this proposal from the response. 'finalize': request firm pricing and inventory hold — transitions a draft proposal to committed with an expires_at hold window. May trigger seller-side approval (HITL). The buyer should not set a time_budget for finalize requests — they represent a commitment to wait for the result. Optional — when omitted, the seller treats the entry as action: 'include'." ), - ] + ] = Action3.include ask: Annotated[ str | None, Field( @@ -104,6 +106,16 @@ class Refine2(AdCPBaseModel): ] = None +class Refine(RootModel[Refine1 | Refine2 | Refine3]): + root: Annotated[Refine1 | Refine2 | Refine3, Field(discriminator="scope")] + + def __getattr__(self, name: str) -> Any: + """Proxy attribute access to the wrapped type.""" + if name.startswith("_"): + raise AttributeError(name) + return getattr(self.root, name) + + class Field1(Enum): product_id = "product_id" name = "name" @@ -162,7 +174,7 @@ class GetProductsRequest(AdCPBaseModel): ), ] = None refine: Annotated[ - list[Refine | Refine1 | Refine2] | None, + list[Refine] | None, Field( description="Array of change requests for iterating on products and proposals from a previous get_products response. Each entry declares a scope (request, product, or proposal) and what the buyer is asking for. Only valid when buying_mode is 'refine'. The seller responds to each entry via refinement_applied in the response, matched by position.", min_length=1, 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 0decaf3f9..c762bcf45 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,27 +1,19 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations from enum import Enum -from typing import Annotated +from typing import Any, Annotated, Literal from adcp.types.base import AdCPBaseModel -from pydantic import ConfigDict, Field +from pydantic import ConfigDict, Field, RootModel from ..core import context as context_1 from ..core import duration, error from ..core import ext as ext_1 -from ..core import pagination_response -from ..core import product as product_1 -from ..core import proposal as proposal_1 - - -class Scope(Enum): - request = "request" - product = "product" - proposal = "proposal" +from ..core import pagination_response, product, proposal class Status(Enum): @@ -30,22 +22,64 @@ class Status(Enum): unable = "unable" -class RefinementAppliedItem(AdCPBaseModel): +class RefinementApplied1(AdCPBaseModel): model_config = ConfigDict( extra="forbid", ) scope: Annotated[ - Scope | None, + Literal["request"], + Field(description="Echoes scope 'request' from the corresponding refine entry."), + ] = "request" + status: Annotated[ + Status, + Field( + description="'applied': the ask was fulfilled. 'partial': the ask was partially fulfilled — see notes for details. 'unable': the seller could not fulfill the ask — see notes for why." + ), + ] + notes: Annotated[ + str | None, Field( - description="Echoes the scope from the corresponding refine entry. Allows orchestrators to cross-validate alignment." + description="Seller explanation of what was done, what couldn't be done, or why. Recommended when status is 'partial' or 'unable'." ), ] = None - id: Annotated[ + + +class RefinementApplied2(AdCPBaseModel): + model_config = ConfigDict( + extra="forbid", + ) + scope: Annotated[ + Literal["product"], + Field(description="Echoes scope 'product' from the corresponding refine entry."), + ] = "product" + product_id: Annotated[ + str, Field(description="Echoes product_id from the corresponding refine entry.") + ] + status: Annotated[ + Status, + Field( + description="'applied': the ask was fulfilled. 'partial': the ask was partially fulfilled — see notes for details. 'unable': the seller could not fulfill the ask — see notes for why." + ), + ] + notes: Annotated[ str | None, Field( - description="Echoes the id from the corresponding refine entry (for product and proposal scopes)." + description="Seller explanation of what was done, what couldn't be done, or why. Recommended when status is 'partial' or 'unable'." ), ] = None + + +class RefinementApplied3(AdCPBaseModel): + model_config = ConfigDict( + extra="forbid", + ) + scope: Annotated[ + Literal["proposal"], + Field(description="Echoes scope 'proposal' from the corresponding refine entry."), + ] = "proposal" + proposal_id: Annotated[ + str, Field(description="Echoes proposal_id from the corresponding refine entry.") + ] status: Annotated[ Status, Field( @@ -60,7 +94,19 @@ class RefinementAppliedItem(AdCPBaseModel): ] = None -class Scope3(Enum): +class RefinementApplied(RootModel[RefinementApplied1 | RefinementApplied2 | RefinementApplied3]): + root: Annotated[ + RefinementApplied1 | RefinementApplied2 | RefinementApplied3, Field(discriminator="scope") + ] + + def __getattr__(self, name: str) -> Any: + """Proxy attribute access to the wrapped type.""" + if name.startswith("_"): + raise AttributeError(name) + return getattr(self.root, name) + + +class Scope(Enum): products = "products" pricing = "pricing" forecast = "forecast" @@ -72,7 +118,7 @@ class IncompleteItem(AdCPBaseModel): extra="forbid", ) scope: Annotated[ - Scope3, + Scope, Field( description="'products': not all inventory sources were searched. 'pricing': products returned but pricing is absent or unconfirmed. 'forecast': products returned but forecast data is absent. 'proposals': proposals were not generated or are incomplete." ), @@ -92,9 +138,9 @@ class GetProductsResponse(AdCPBaseModel): model_config = ConfigDict( extra="allow", ) - products: Annotated[list[product_1.Product], Field(description="Array of matching products")] + products: Annotated[list[product.Product], Field(description="Array of matching products")] proposals: Annotated[ - list[proposal_1.Proposal] | None, + list[proposal.Proposal] | None, Field( description="Optional array of proposed media plans with budget allocations across products. Publishers include proposals when they can provide strategic guidance based on the brief. Proposals are actionable - buyers can refine them via follow-up get_products calls within the same session, or execute them directly via create_media_buy." ), @@ -116,9 +162,9 @@ class GetProductsResponse(AdCPBaseModel): ), ] = None refinement_applied: Annotated[ - list[RefinementAppliedItem] | None, + list[RefinementApplied] | None, Field( - description="Seller's response to each change request in the refine array, matched by position. Each entry acknowledges whether the corresponding ask was applied, partially applied, or unable to be fulfilled. MUST contain the same number of entries in the same order as the request's refine array. Only present when the request used buying_mode: 'refine'." + description="Seller's response to each change request in the refine array, matched by position. Each entry acknowledges whether the corresponding ask was applied, partially applied, or unable to be fulfilled. MUST contain the same number of entries in the same order as the request's refine array. Only present when the request used buying_mode: 'refine'. Each entry MUST echo the request entry's scope and — for product and proposal scopes — the matching id field (product_id or proposal_id), so orchestrators can cross-validate alignment." ), ] = None incomplete: Annotated[ 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 0d42d27cf..6b48d60cd 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 6ffbf4904..7fb03fc64 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/log_event_request.py b/src/adcp/types/generated_poc/media_buy/log_event_request.py index f694c37d2..f9901f07d 100644 --- a/src/adcp/types/generated_poc/media_buy/log_event_request.py +++ b/src/adcp/types/generated_poc/media_buy/log_event_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/log_event_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/log_event_response.py b/src/adcp/types/generated_poc/media_buy/log_event_response.py index bb118ce76..bf5d84f77 100644 --- a/src/adcp/types/generated_poc/media_buy/log_event_response.py +++ b/src/adcp/types/generated_poc/media_buy/log_event_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/log_event_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 2fc42d9b1..d033ba70d 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/package_update.py b/src/adcp/types/generated_poc/media_buy/package_update.py index c4242384c..6e8d9d4fe 100644 --- a/src/adcp/types/generated_poc/media_buy/package_update.py +++ b/src/adcp/types/generated_poc/media_buy/package_update.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/package_update.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 633252dd2..71dd0d036 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 f956a9f03..692dc6043 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/sync_audiences_request.py b/src/adcp/types/generated_poc/media_buy/sync_audiences_request.py index 268297dcf..87f1b52c1 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_audiences_request.py +++ b/src/adcp/types/generated_poc/media_buy/sync_audiences_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_audiences_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/sync_audiences_response.py b/src/adcp/types/generated_poc/media_buy/sync_audiences_response.py index ab58e9efa..463da9768 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_audiences_response.py +++ b/src/adcp/types/generated_poc/media_buy/sync_audiences_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_audiences_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/sync_catalogs_async_response_input_required.py b/src/adcp/types/generated_poc/media_buy/sync_catalogs_async_response_input_required.py index 5c261f615..89d1d756f 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_catalogs_async_response_input_required.py +++ b/src/adcp/types/generated_poc/media_buy/sync_catalogs_async_response_input_required.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_catalogs_async_response_input_required.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/sync_catalogs_async_response_submitted.py b/src/adcp/types/generated_poc/media_buy/sync_catalogs_async_response_submitted.py index d6c7c3ad4..55c46d8d0 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_catalogs_async_response_submitted.py +++ b/src/adcp/types/generated_poc/media_buy/sync_catalogs_async_response_submitted.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_catalogs_async_response_submitted.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/sync_catalogs_async_response_working.py b/src/adcp/types/generated_poc/media_buy/sync_catalogs_async_response_working.py index 3e1e0d4e0..3cf4a62ee 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_catalogs_async_response_working.py +++ b/src/adcp/types/generated_poc/media_buy/sync_catalogs_async_response_working.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_catalogs_async_response_working.json -# timestamp: 2026-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/sync_catalogs_request.py b/src/adcp/types/generated_poc/media_buy/sync_catalogs_request.py index a397df559..665c4c416 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_catalogs_request.py +++ b/src/adcp/types/generated_poc/media_buy/sync_catalogs_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_catalogs_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/sync_catalogs_response.py b/src/adcp/types/generated_poc/media_buy/sync_catalogs_response.py index bae0de3af..664183c43 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_catalogs_response.py +++ b/src/adcp/types/generated_poc/media_buy/sync_catalogs_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_catalogs_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/sync_event_sources_request.py b/src/adcp/types/generated_poc/media_buy/sync_event_sources_request.py index a5db21498..5366da7ee 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_event_sources_request.py +++ b/src/adcp/types/generated_poc/media_buy/sync_event_sources_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_event_sources_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/media_buy/sync_event_sources_response.py b/src/adcp/types/generated_poc/media_buy/sync_event_sources_response.py index 5b44a7713..ba202d340 100644 --- a/src/adcp/types/generated_poc/media_buy/sync_event_sources_response.py +++ b/src/adcp/types/generated_poc/media_buy/sync_event_sources_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/sync_event_sources_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 3177ef440..6b60ba97d 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-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 20c9592d8..5aaee3ccc 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-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 adfd2a012..cb3089ae4 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-04-16T02:55:59+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 16b9584b3..f1b86a82d 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-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 fd14338fd..58fdd5dc1 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/pricing_options/cpa_option.py b/src/adcp/types/generated_poc/pricing_options/cpa_option.py index 971b2d62d..c13831a19 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpa_option.py +++ b/src/adcp/types/generated_poc/pricing_options/cpa_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/cpa_option.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -23,7 +23,7 @@ class CpaPricingOption(AdCPBaseModel): ] pricing_model: Annotated[ Literal["cpa"], Field(description="Cost per acquisition (conversion event)") - ] + ] = "cpa" event_type: Annotated[ event_type_1.EventType, Field( 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 815f8623c..a653f9163 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -21,7 +21,7 @@ class CpcPricingOption(AdCPBaseModel): pricing_option_id: Annotated[ str, Field(description="Unique identifier for this pricing option within the product") ] - pricing_model: Annotated[Literal["cpc"], Field(description="Cost per click")] + pricing_model: Annotated[Literal["cpc"], Field(description="Cost per click")] = "cpc" currency: Annotated[ str, Field( 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 b589843a8..1293feba8 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-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -23,7 +23,7 @@ class CpcvPricingOption(AdCPBaseModel): ] pricing_model: Annotated[ Literal["cpcv"], Field(description="Cost per completed view (100% completion)") - ] + ] = "cpcv" currency: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/pricing_options/cpm_option.py b/src/adcp/types/generated_poc/pricing_options/cpm_option.py index d7285c8c6..d8eb35601 100644 --- a/src/adcp/types/generated_poc/pricing_options/cpm_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_option.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -21,7 +21,9 @@ class CpmPricingOption(AdCPBaseModel): pricing_option_id: Annotated[ str, Field(description="Unique identifier for this pricing option within the product") ] - pricing_model: Annotated[Literal["cpm"], Field(description="Cost per 1,000 impressions")] + pricing_model: Annotated[Literal["cpm"], Field(description="Cost per 1,000 impressions")] = ( + "cpm" + ) currency: Annotated[ str, Field( 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 8b6bbc4e6..ed72f5df4 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -43,7 +43,9 @@ class CppPricingOption(AdCPBaseModel): pricing_option_id: Annotated[ str, Field(description="Unique identifier for this pricing option within the product") ] - pricing_model: Annotated[Literal["cpp"], Field(description="Cost per Gross Rating Point")] + pricing_model: Annotated[Literal["cpp"], Field(description="Cost per Gross Rating Point")] = ( + "cpp" + ) currency: Annotated[ str, Field( 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 d909c7cf8..0e377302c 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -46,7 +46,9 @@ class CpvPricingOption(AdCPBaseModel): pricing_option_id: Annotated[ str, Field(description="Unique identifier for this pricing option within the product") ] - pricing_model: Annotated[Literal["cpv"], Field(description="Cost per view at threshold")] + pricing_model: Annotated[Literal["cpv"], Field(description="Cost per view at threshold")] = ( + "cpv" + ) currency: Annotated[ str, Field( 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 f532ead34..21ced4a10 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -20,7 +20,7 @@ class Parameters(AdCPBaseModel): ) type: Annotated[ Literal["dooh"], Field(description="Discriminator identifying this as DOOH parameters") - ] + ] = "dooh" sov_percentage: Annotated[ float | None, Field(description="Guaranteed share of voice as a percentage (0-100)", ge=0.0, le=100.0), @@ -63,7 +63,7 @@ class FlatRatePricingOption(AdCPBaseModel): ] pricing_model: Annotated[ Literal["flat_rate"], Field(description="Fixed cost regardless of delivery volume") - ] + ] = "flat_rate" currency: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/pricing_options/price_breakdown.py b/src/adcp/types/generated_poc/pricing_options/price_breakdown.py index bba713335..8b5d9a1ef 100644 --- a/src/adcp/types/generated_poc/pricing_options/price_breakdown.py +++ b/src/adcp/types/generated_poc/pricing_options/price_breakdown.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/price_breakdown.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/pricing_options/price_guidance.py b/src/adcp/types/generated_poc/pricing_options/price_guidance.py index 160f0c0dd..bd1a8bf8c 100644 --- a/src/adcp/types/generated_poc/pricing_options/price_guidance.py +++ b/src/adcp/types/generated_poc/pricing_options/price_guidance.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/price_guidance.json -# timestamp: 2026-02-23T01:56:40+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/pricing_options/time_option.py b/src/adcp/types/generated_poc/pricing_options/time_option.py index 9fb3f296a..af3d972b1 100644 --- a/src/adcp/types/generated_poc/pricing_options/time_option.py +++ b/src/adcp/types/generated_poc/pricing_options/time_option.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: pricing_options/time_option.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -54,7 +54,7 @@ class TimeBasedPricingOption(AdCPBaseModel): pricing_model: Annotated[ Literal["time"], Field(description="Cost per time unit - rate scales with campaign duration"), - ] + ] = "time" currency: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/pricing_options/vcpm_option.py b/src/adcp/types/generated_poc/pricing_options/vcpm_option.py index 956c65646..ce8f5554f 100644 --- a/src/adcp/types/generated_poc/pricing_options/vcpm_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_option.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -23,7 +23,7 @@ class VcpmPricingOption(AdCPBaseModel): ] pricing_model: Annotated[ Literal["vcpm"], Field(description="Cost per 1,000 viewable impressions (MRC standard)") - ] + ] = "vcpm" currency: Annotated[ str, Field( diff --git a/src/adcp/types/generated_poc/property/authorization_result.py b/src/adcp/types/generated_poc/property/authorization_result.py index 4ef1e826e..228bd8ac3 100644 --- a/src/adcp/types/generated_poc/property/authorization_result.py +++ b/src/adcp/types/generated_poc/property/authorization_result.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/authorization_result.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 b10a845e1..6230378ca 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -19,7 +19,7 @@ class BasePropertySource1(AdCPBaseModel): selection_type: Annotated[ Literal["publisher_tags"], Field(description="Discriminator indicating selection by property tags within a publisher"), - ] + ] = "publisher_tags" publisher_domain: Annotated[ str, Field( @@ -45,7 +45,7 @@ class BasePropertySource2(AdCPBaseModel): Field( description="Discriminator indicating selection by specific property IDs within a publisher" ), - ] + ] = "publisher_ids" publisher_domain: Annotated[ str, Field( @@ -66,7 +66,7 @@ class BasePropertySource3(AdCPBaseModel): selection_type: Annotated[ Literal["identifiers"], Field(description="Discriminator indicating selection by direct identifiers"), - ] + ] = "identifiers" identifiers: Annotated[ list[identifier.Identifier], Field(description="Direct property identifiers (domains, app IDs, etc.)", min_length=1), 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 82b499ec1..99fede54c 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-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 f5b50eb4a..2098aeb43 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 92e7626ad..5a16575cd 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-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 a36e8b74a..8f569f58c 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/property/delivery_record.py b/src/adcp/types/generated_poc/property/delivery_record.py index 85d1f9c75..cd9b11b40 100644 --- a/src/adcp/types/generated_poc/property/delivery_record.py +++ b/src/adcp/types/generated_poc/property/delivery_record.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/delivery_record.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 936d6db85..4dee74599 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-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 5fd6c92f7..cf25ada31 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -14,6 +14,7 @@ from ..core import identifier, pagination_response from . import property_list + _list = list # alias to avoid shadowing by field name 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 c40d1bd64..830464ada 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-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 33b5e61c3..13b252d52 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/property/property_error.py b/src/adcp/types/generated_poc/property/property_error.py index 00f928568..11330bfce 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/property/property_feature.py b/src/adcp/types/generated_poc/property/property_feature.py index 9f76d1f1d..66ebf465f 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 208e3eb31..3b13267be 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/property/property_feature_result.py b/src/adcp/types/generated_poc/property/property_feature_result.py index fdcaa753a..6eef56a95 100644 --- a/src/adcp/types/generated_poc/property/property_feature_result.py +++ b/src/adcp/types/generated_poc/property/property_feature_result.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/property_feature_result.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/property/property_feature_value.py b/src/adcp/types/generated_poc/property/property_feature_value.py index 748848e26..228d83acc 100644 --- a/src/adcp/types/generated_poc/property/property_feature_value.py +++ b/src/adcp/types/generated_poc/property/property_feature_value.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/property_feature_value.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/property/property_list.py b/src/adcp/types/generated_poc/property/property_list.py index 567897206..554e37c25 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-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 ceb893dee..6edc59b05 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-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -40,7 +40,9 @@ class PropertyListChangedWebhook(AdCPBaseModel): pattern="^[A-Za-z0-9_.:-]{16,255}$", ), ] - event: Annotated[Literal["property_list_changed"], Field(description="The event type")] + event: Annotated[Literal["property_list_changed"], Field(description="The event type")] = ( + "property_list_changed" + ) 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 change_summary: Annotated[ 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 25df439d6..9499ba087 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 873b948c6..6cac42161 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-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 22a65aae7..294350ccd 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/property/validate_property_delivery_request.py b/src/adcp/types/generated_poc/property/validate_property_delivery_request.py index 10783a1f3..8d0489dd6 100644 --- a/src/adcp/types/generated_poc/property/validate_property_delivery_request.py +++ b/src/adcp/types/generated_poc/property/validate_property_delivery_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/validate_property_delivery_request.json -# timestamp: 2026-04-19T02:40:53+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/property/validate_property_delivery_response.py b/src/adcp/types/generated_poc/property/validate_property_delivery_response.py index d754ae44c..7a53b19f6 100644 --- a/src/adcp/types/generated_poc/property/validate_property_delivery_response.py +++ b/src/adcp/types/generated_poc/property/validate_property_delivery_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/validate_property_delivery_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/property/validation_result.py b/src/adcp/types/generated_poc/property/validation_result.py index 62def43ec..07779ee0b 100644 --- a/src/adcp/types/generated_poc/property/validation_result.py +++ b/src/adcp/types/generated_poc/property/validation_result.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: property/validation_result.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -22,7 +22,7 @@ class Status(Enum): unidentified = "unidentified" -class Status52(Enum): +class Status56(Enum): passed = "passed" failed = "failed" warning = "warning" @@ -50,7 +50,7 @@ class Feature(AdCPBaseModel): description="Which feature was evaluated. Data features come from the governance agent's feature catalog (e.g., 'mfa_score', 'carbon_score'). Record-level structural checks use reserved namespaces: 'record:list_membership', 'record:excluded', 'delivery:seller_authorization', 'delivery:click_url_presence'. Reserved prefixes: 'record:', 'delivery:'." ), ] - status: Status52 + status: Status56 policy_id: Annotated[ str | None, Field( 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 index 615d91aec..d7327c4dc 100644 --- a/src/adcp/types/generated_poc/protocol/get_adcp_capabilities_request.py +++ b/src/adcp/types/generated_poc/protocol/get_adcp_capabilities_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: protocol/get_adcp_capabilities_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 5b2451b55..32da54c40 100644 --- a/src/adcp/types/generated_poc/protocol/get_adcp_capabilities_response.py +++ b/src/adcp/types/generated_poc/protocol/get_adcp_capabilities_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: protocol/get_adcp_capabilities_response.json -# timestamp: 2026-04-21T22:41:55+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 d74f4693c..0d67e4b42 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 703dff3b3..54b6c8b68 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 ac55e915f..06082f03f 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 29a3beda8..1cd33ab83 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-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_capabilities.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_capabilities.py index 85072cb18..288a2a071 100644 --- a/src/adcp/types/generated_poc/sponsored_intelligence/si_capabilities.py +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_capabilities.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: sponsored_intelligence/si_capabilities.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 30fa9f81c..9e6dcc5c7 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: sponsored_intelligence/si_get_offering_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -9,6 +9,7 @@ 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 @@ -27,12 +28,13 @@ class SiGetOfferingRequest(AdCPBaseModel): offering_id: Annotated[ str, Field(description="Offering identifier from the catalog to get details for") ] - context: Annotated[ + intent: 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." + description="Optional natural language description of user intent for personalized results (e.g., 'mens size 14 near Cincinnati'). Must be anonymous - no PII." ), ] = None + context: context_1.ContextObject | None = None include_products: Annotated[ bool | None, Field(description="Whether to include matching products in the response") ] = False 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 index 1a3ff85cf..eced02121 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: sponsored_intelligence/si_get_offering_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_identity.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_identity.py index 2a6e08d64..5fdf30cbc 100644 --- a/src/adcp/types/generated_poc/sponsored_intelligence/si_identity.py +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_identity.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: sponsored_intelligence/si_identity.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 90f89b78d..9e12ae96f 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: sponsored_intelligence/si_initiate_session_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -9,6 +9,7 @@ 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 . import si_capabilities, si_identity @@ -25,9 +26,13 @@ class SiInitiateSessionRequest(AdCPBaseModel): le=99, ), ] = None - context: Annotated[ - str, Field(description="Conversation handoff from the host describing what the user needs") + intent: Annotated[ + str, + Field( + description="Natural language description of user intent — the conversation handoff from the host describing what the user needs from the brand agent" + ), ] + context: context_1.ContextObject | None = None identity: si_identity.SiIdentity media_buy_id: Annotated[ str | None, Field(description="AdCP media buy ID if session was triggered by advertising") 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 index 816a37814..deb1393a1 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: sponsored_intelligence/si_initiate_session_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 3d86dee5a..29ec21bc4 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: sponsored_intelligence/si_send_message_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 7971da9b6..15f5a8782 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: sponsored_intelligence/si_send_message_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 445c750e3..b5156cf09 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: sponsored_intelligence/si_terminate_session_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 3126badb9..be77b3c4b 100644 --- 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 @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: sponsored_intelligence/si_terminate_session_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations 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 index 9bcfb69d2..06dba7fd5 100644 --- a/src/adcp/types/generated_poc/sponsored_intelligence/si_ui_element.py +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_ui_element.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: sponsored_intelligence/si_ui_element.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/tmp/available_package.py b/src/adcp/types/generated_poc/tmp/available_package.py index 7929bd594..6f2c5fe4e 100644 --- a/src/adcp/types/generated_poc/tmp/available_package.py +++ b/src/adcp/types/generated_poc/tmp/available_package.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: tmp/available_package.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/tmp/context_match_request.py b/src/adcp/types/generated_poc/tmp/context_match_request.py index 6c77b3721..dd2ea526c 100644 --- a/src/adcp/types/generated_poc/tmp/context_match_request.py +++ b/src/adcp/types/generated_poc/tmp/context_match_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: tmp/context_match_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -191,7 +191,7 @@ class ContextMatchRequest(AdCPBaseModel): type: Annotated[ Literal["context_match_request"], Field(description="Message type discriminator for deserialization."), - ] + ] = "context_match_request" protocol_version: Annotated[ str | None, Field( diff --git a/src/adcp/types/generated_poc/tmp/context_match_response.py b/src/adcp/types/generated_poc/tmp/context_match_response.py index 40bae7cdd..2255b6f09 100644 --- a/src/adcp/types/generated_poc/tmp/context_match_response.py +++ b/src/adcp/types/generated_poc/tmp/context_match_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: tmp/context_match_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -39,7 +39,7 @@ class ContextMatchResponse(AdCPBaseModel): type: Annotated[ Literal["context_match_response"], Field(description="Message type discriminator for deserialization."), - ] + ] = "context_match_response" request_id: Annotated[ str, Field(description="Echoed request identifier from the context match request") ] diff --git a/src/adcp/types/generated_poc/tmp/error.py b/src/adcp/types/generated_poc/tmp/error.py index cbc46c8ac..be2c4c1f3 100644 --- a/src/adcp/types/generated_poc/tmp/error.py +++ b/src/adcp/types/generated_poc/tmp/error.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: tmp/error.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -26,7 +26,7 @@ class TmpError(AdCPBaseModel): ) type: Annotated[ Literal["error"], Field(description="Message type discriminator for deserialization.") - ] + ] = "error" request_id: Annotated[ str, Field(description="Echoed request identifier from the original request") ] diff --git a/src/adcp/types/generated_poc/tmp/identity_match_request.py b/src/adcp/types/generated_poc/tmp/identity_match_request.py index 0006f7315..ac2cb404c 100644 --- a/src/adcp/types/generated_poc/tmp/identity_match_request.py +++ b/src/adcp/types/generated_poc/tmp/identity_match_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: tmp/identity_match_request.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -68,7 +68,7 @@ class IdentityMatchRequest(AdCPBaseModel): type: Annotated[ Literal["identity_match_request"], Field(description="Message type discriminator for deserialization."), - ] + ] = "identity_match_request" protocol_version: Annotated[ str | None, Field( diff --git a/src/adcp/types/generated_poc/tmp/identity_match_response.py b/src/adcp/types/generated_poc/tmp/identity_match_response.py index ac140cf95..2d622b367 100644 --- a/src/adcp/types/generated_poc/tmp/identity_match_response.py +++ b/src/adcp/types/generated_poc/tmp/identity_match_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: tmp/identity_match_response.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations @@ -17,7 +17,7 @@ class IdentityMatchResponse(AdCPBaseModel): type: Annotated[ Literal["identity_match_response"], Field(description="Message type discriminator for deserialization."), - ] + ] = "identity_match_response" request_id: Annotated[ str, Field(description="Echoed request identifier from the identity match request") ] diff --git a/src/adcp/types/generated_poc/tmp/offer.py b/src/adcp/types/generated_poc/tmp/offer.py index d9454aad5..1b9832139 100644 --- a/src/adcp/types/generated_poc/tmp/offer.py +++ b/src/adcp/types/generated_poc/tmp/offer.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: tmp/offer.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/tmp/offer_price.py b/src/adcp/types/generated_poc/tmp/offer_price.py index 018d9b160..4bbf7600d 100644 --- a/src/adcp/types/generated_poc/tmp/offer_price.py +++ b/src/adcp/types/generated_poc/tmp/offer_price.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: tmp/offer_price.json -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/tmp/provider_registration.py b/src/adcp/types/generated_poc/tmp/provider_registration.py index e9e5a2590..765c87c23 100644 --- a/src/adcp/types/generated_poc/tmp/provider_registration.py +++ b/src/adcp/types/generated_poc/tmp/provider_registration.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: tmp/provider_registration.json -# timestamp: 2026-04-18T19:31:26+00:00 +# timestamp: 2026-04-22T04:27:52+00:00 from __future__ import annotations diff --git a/tests/test_literal_discriminator_defaults.py b/tests/test_literal_discriminator_defaults.py new file mode 100644 index 000000000..4232acaaf --- /dev/null +++ b/tests/test_literal_discriminator_defaults.py @@ -0,0 +1,171 @@ +"""Tests for the post-generation ``Literal[]`` defaults +injection in ``scripts/post_generate_fixes.py``. + +The injection turns spec-required discriminator fields (whose type is +``Literal['x']`` with a single value) into defaulted fields. Wire +consumers are unaffected — the Literal type still enforces the tag. +In-process construction becomes ergonomic — ``TextContent(content='x')`` +works without having to repeat ``asset_type='text'``. + +These tests pin the behavior across a sampling of Asset, Pricing, and +Response types so a future regen that breaks the injection fails loudly +at the right layer. +""" + +from __future__ import annotations + +import pytest + + +class TestAssetContentDefaults: + """Asset-content types all default their ``asset_type`` + discriminator to the correct tag.""" + + def test_text_content_defaults_asset_type(self) -> None: + from adcp.types import TextContent + + t = TextContent(content="hello") + assert t.asset_type == "text" + assert t.content == "hello" + + def test_html_content_defaults_asset_type(self) -> None: + from adcp.types import HtmlContent + + h = HtmlContent(content="

x

") + assert h.asset_type == "html" + + def test_css_content_defaults_asset_type(self) -> None: + from adcp.types import CssContent + + c = CssContent(content="body{}") + assert c.asset_type == "css" + + def test_javascript_content_defaults_asset_type(self) -> None: + from adcp.types import JavascriptContent + + j = JavascriptContent(content="alert(1)") + assert j.asset_type == "javascript" + + def test_url_content_defaults_asset_type(self) -> None: + from adcp.types import UrlContent + + u = UrlContent(url="https://example.com/asset.jpg") + assert u.asset_type == "url" + + +class TestVastDaastDiscriminators: + """VAST/DAAST have two discriminators: ``asset_type`` (vast/daast) + AND ``delivery_type`` (url/inline). Both are single-value Literals + per the spec's oneOf-of-oneOfs structure; both get defaults.""" + + def test_url_vast_asset_defaults_both_discriminators(self) -> None: + from adcp.types.aliases import UrlVastAsset + + a = UrlVastAsset(url="https://vast.example.com/ad.xml") + assert a.asset_type == "vast" + assert a.delivery_type == "url" + + def test_inline_vast_asset_defaults_both_discriminators(self) -> None: + from adcp.types.aliases import InlineVastAsset + + a = InlineVastAsset(content="...") + assert a.asset_type == "vast" + assert a.delivery_type == "inline" + + def test_url_daast_asset_defaults_both_discriminators(self) -> None: + from adcp.types.aliases import UrlDaastAsset + + a = UrlDaastAsset(url="https://daast.example.com/ad.xml") + assert a.asset_type == "daast" + assert a.delivery_type == "url" + + +class TestDefaultsPreserveValidation: + """The injected defaults are a construction convenience. The + ``Literal`` type still rejects any OTHER value passed explicitly — + defaulting doesn't weaken validation.""" + + def test_wrong_explicit_asset_type_rejected(self) -> None: + from pydantic import ValidationError + + from adcp.types import TextContent + + with pytest.raises(ValidationError): + TextContent(asset_type="html", content="x") # type: ignore[arg-type] + + def test_wrong_explicit_delivery_type_rejected(self) -> None: + from pydantic import ValidationError + + from adcp.types.aliases import UrlVastAsset + + with pytest.raises(ValidationError): + UrlVastAsset( + delivery_type="inline", # type: ignore[arg-type] + url="https://vast.example.com/ad.xml", + ) + + +class TestDefaultsHonourWireFormat: + """Validating a dict (wire format) still works — the defaults are + injected via field metadata, not by pre-filling the input.""" + + def test_text_content_from_wire_dict(self) -> None: + from adcp.types import TextContent + + t = TextContent.model_validate({"asset_type": "text", "content": "hi"}) + assert t.asset_type == "text" + assert t.content == "hi" + + def test_text_content_from_wire_dict_without_asset_type_still_works(self) -> None: + """Wire consumers that omit the discriminator also get the + default — useful for minimal client implementations.""" + from adcp.types import TextContent + + t = TextContent.model_validate({"content": "hi"}) + assert t.asset_type == "text" + + +class TestInjectorBehavior: + """Meta-tests pinning the injector's pattern-match semantics. If + these fail, the post-gen script's scope has drifted.""" + + def test_injector_skips_multi_value_literals(self) -> None: + """``Literal['a', 'b']`` fields stay required — there's no + single correct default. The spec is saying "user must pick", + and we must not pretend otherwise.""" + import ast + + from scripts.post_generate_fixes import _extract_single_literal_value + + # Annotated[Literal['a', 'b'], ...] + module = ast.parse("x: Annotated[Literal['a', 'b'], Field()]") + ann = module.body[0].annotation # type: ignore[attr-defined] + assert _extract_single_literal_value(ann) is None + + def test_injector_extracts_single_literal_value(self) -> None: + import ast + + from scripts.post_generate_fixes import _extract_single_literal_value + + module = ast.parse("x: Annotated[Literal['text'], Field()]") + ann = module.body[0].annotation # type: ignore[attr-defined] + assert _extract_single_literal_value(ann) == "text" + + def test_injector_extracts_bare_literal(self) -> None: + """``Literal['x']`` without Annotated wrap also works.""" + import ast + + from scripts.post_generate_fixes import _extract_single_literal_value + + module = ast.parse("x: Literal['text']") + ann = module.body[0].annotation # type: ignore[attr-defined] + assert _extract_single_literal_value(ann) == "text" + + def test_injector_skips_non_literal_annotations(self) -> None: + import ast + + from scripts.post_generate_fixes import _extract_single_literal_value + + module = ast.parse("x: str") + ann = module.body[0].annotation # type: ignore[attr-defined] + assert _extract_single_literal_value(ann) is None