From 1d24860c41556275dc749e41b3cef6d96101d4fd Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Wed, 1 Jul 2026 07:36:48 +0100 Subject: [PATCH 1/4] feat(protocol): support AdCP 3.1.1 schemas --- README.md | 4 +- SCHEMA_DELTAS.md | 136 ++++-------------- schemas/cache/3.1/adagents.json | 14 +- schemas/cache/3.1/brand.json | 20 +-- .../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 +- .../3.1/bundled/core/tasks-get-request.json | 2 +- .../3.1/bundled/core/tasks-get-response.json | 102 +++++++------ .../3.1/bundled/core/tasks-list-request.json | 2 +- .../3.1/bundled/core/tasks-list-response.json | 2 +- .../get-creative-delivery-request.json | 2 +- .../get-creative-delivery-response.json | 34 +++-- .../get-creative-features-request.json | 34 +++-- .../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 | 34 +++-- .../creative/list-transformers-request.json | 2 +- .../creative/list-transformers-response.json | 2 +- .../creative/preview-creative-request.json | 66 +++++---- .../creative/preview-creative-response.json | 34 +++-- .../creative/sync-creatives-request.json | 34 +++-- .../creative/sync-creatives-response.json | 2 +- .../creative/validate-input-request.json | 34 +++-- .../creative/validate-input-response.json | 2 +- .../media-buy/build-creative-request.json | 34 +++-- .../media-buy/build-creative-response.json | 98 +++++++------ .../media-buy/create-media-buy-request.json | 34 +++-- .../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 | 6 +- .../media-buy/get-products-response.json | 6 +- .../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 | 34 +++-- .../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 | 66 +++++---- .../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 | 7 +- .../protocol/get-task-status-request.json | 2 +- .../protocol/get-task-status-response.json | 102 +++++++------ .../bundled/protocol/list-tasks-request.json | 2 +- .../bundled/protocol/list-tasks-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 | 2 +- .../si-get-offering-response.json | 2 +- .../si-initiate-session-request.json | 2 +- .../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/3.1/core/assets/vast-asset.json | 2 +- .../cache/3.1/core/assets/video-asset.json | 7 +- .../3.1/core/registry-feed-response.json | 44 +++++- schemas/cache/3.1/core/x-entity-types.json | 2 +- .../cache/3.1/creative/asset-types/index.json | 37 ++++- schemas/cache/3.1/enums/delivery-type.json | 2 +- schemas/cache/3.1/extensions/index.json | 2 +- schemas/cache/3.1/index.json | 55 +++++-- schemas/cache/3.1/manifest.json | 6 +- schemas/cache/3.1/manifest.schema.json | 4 +- .../3.1/media-buy/get-products-request.json | 3 +- .../3.1/media-buy/get-products-response.json | 3 +- .../get-adcp-capabilities-response.json | 5 + .../3.1/tmp/identity-match-response.json | 50 ------- .../available-package.json | 0 .../context-match-request.json | 0 .../context-match-response.json | 0 .../3.1/{tmp => trusted-match}/error.json | 0 .../identity-match-request.json | 0 .../identity-match-response.json | 107 ++++++++++++++ .../{tmp => trusted-match}/offer-price.json | 0 .../3.1/{tmp => trusted-match}/offer.json | 0 .../provider-registration.json | 17 ++- scripts/consolidate_exports.py | 5 + scripts/post_generate_fixes.py | 115 +++++++++++++++ src/adcp/ADCP_VERSION | 2 +- src/adcp/__init__.py | 6 + src/adcp/client.py | 8 +- src/adcp/types/__init__.py | 5 + src/adcp/types/_eager.py | 4 + src/adcp/types/_generated.py | 38 +++-- src/adcp/types/aliases.py | 9 ++ src/adcp/types/generated_poc/adagents.py | 30 ++-- .../types/generated_poc/brand/__init__.py | 22 +-- .../get_adcp_capabilities_response.py | 8 +- .../generated_poc/core/assets/vast_asset.py | 4 +- .../generated_poc/core/assets/video_asset.py | 18 ++- .../core/registry_feed_response.py | 35 ++++- .../types/generated_poc/manifest_schema.py | 6 +- .../media_buy/get_products_request.py | 9 +- .../media_buy/get_products_response.py | 9 +- .../get_adcp_capabilities_response.py | 8 +- .../tmp/identity_match_response.py | 45 ------ .../{tmp => trusted_match}/__init__.py | 2 +- .../available_package.py | 4 +- .../context_match_request.py | 4 +- .../context_match_response.py | 4 +- .../{tmp => trusted_match}/error.py | 4 +- .../identity_match_request.py | 4 +- .../trusted_match/identity_match_response.py | 115 +++++++++++++++ .../{tmp => trusted_match}/offer.py | 4 +- .../{tmp => trusted_match}/offer_price.py | 4 +- .../provider_registration.py | 70 ++++++++- tests/fixtures/public_api_snapshot.json | 4 + tests/test_collision_aliases.py | 14 ++ tests/test_trusted_match_validation.py | 73 ++++++++++ 149 files changed, 1376 insertions(+), 739 deletions(-) delete mode 100644 schemas/cache/3.1/tmp/identity-match-response.json rename schemas/cache/3.1/{tmp => trusted-match}/available-package.json (100%) rename schemas/cache/3.1/{tmp => trusted-match}/context-match-request.json (100%) rename schemas/cache/3.1/{tmp => trusted-match}/context-match-response.json (100%) rename schemas/cache/3.1/{tmp => trusted-match}/error.json (100%) rename schemas/cache/3.1/{tmp => trusted-match}/identity-match-request.json (100%) create mode 100644 schemas/cache/3.1/trusted-match/identity-match-response.json rename schemas/cache/3.1/{tmp => trusted-match}/offer-price.json (100%) rename schemas/cache/3.1/{tmp => trusted-match}/offer.json (100%) rename schemas/cache/3.1/{tmp => trusted-match}/provider-registration.json (71%) delete mode 100644 src/adcp/types/generated_poc/tmp/identity_match_response.py rename src/adcp/types/generated_poc/{tmp => trusted_match}/__init__.py (60%) rename src/adcp/types/generated_poc/{tmp => trusted_match}/available_package.py (94%) rename src/adcp/types/generated_poc/{tmp => trusted_match}/context_match_request.py (99%) rename src/adcp/types/generated_poc/{tmp => trusted_match}/context_match_response.py (95%) rename src/adcp/types/generated_poc/{tmp => trusted_match}/error.py (94%) rename src/adcp/types/generated_poc/{tmp => trusted_match}/identity_match_request.py (99%) create mode 100644 src/adcp/types/generated_poc/trusted_match/identity_match_response.py rename src/adcp/types/generated_poc/{tmp => trusted_match}/offer.py (97%) rename src/adcp/types/generated_poc/{tmp => trusted_match}/offer_price.py (89%) rename src/adcp/types/generated_poc/{tmp => trusted_match}/provider_registration.py (61%) create mode 100644 tests/test_trusted_match_validation.py diff --git a/README.md b/README.md index a341e6436..bcb5e2be5 100644 --- a/README.md +++ b/README.md @@ -276,14 +276,14 @@ async with ADCPMultiAgentClient( ## AdCP version support -The 6.x line is built against **AdCP 3.1.0 stable** and natively validates +The 6.x line is built against **AdCP 3.1.1 stable** and natively validates both AdCP 3.0 and 3.1 wire shapes. Check the versions at runtime: ```python import adcp adcp.get_adcp_sdk_version() # SDK package version, e.g. "6.4.1" -adcp.get_adcp_spec_version() # AdCP spec this build targets, e.g. "3.1.0" +adcp.get_adcp_spec_version() # AdCP spec this build targets, e.g. "3.1.1" ``` If you talk to an agent on a newer spec than this SDK validates, the response diff --git a/SCHEMA_DELTAS.md b/SCHEMA_DELTAS.md index 99251c322..6c2706c32 100644 --- a/SCHEMA_DELTAS.md +++ b/SCHEMA_DELTAS.md @@ -2,112 +2,36 @@ ## Files added -- `sponsored_intelligence/si_context_use.py` — SiContextUse -- `sponsored_intelligence/si_sponsored_context.py` — Account, DeclaredBy, DisclosureObligation, Jurisdiction, PayingPrincipal, Proximity, Role, SiSponsoredContext, Timing -- `sponsored_intelligence/si_sponsored_context_receipt.py` — DisclosureCommitment, HostReceipt, SiSponsoredContextReceipt, Status, Status204 +- `trusted_match/available_package.py` — AvailablePackage +- `trusted_match/context_match_request.py` — ArtifactRef, ContextMatchRequest, ContextSignals, Geo, Keyword, Metro, Sentiment, Type +- `trusted_match/context_match_response.py` — ContextMatchResponse, Signals, TargetingKv +- `trusted_match/error.py` — Code, TmpError +- `trusted_match/identity_match_request.py` — Attestation, Consent, Identity, IdentityMatchRequest, SealedCredential, VerificationLevel +- `trusted_match/identity_match_response.py` — IdentityMatchResponse, TmpxMacro, TmpxProviders +- `trusted_match/offer.py` — Offer +- `trusted_match/offer_price.py` — Model, OfferPrice +- `trusted_match/provider_registration.py` — Country, Status, TmpProviderRegistration, TmpProviderRegistration1, TmpProviderRegistration2, TmpxMacro + +## Files removed + +- `tmp/available_package.py` — AvailablePackage +- `tmp/context_match_request.py` — ArtifactRef, ContextMatchRequest, ContextSignals, Geo, Keyword, Metro, Sentiment, Type +- `tmp/context_match_response.py` — ContextMatchResponse, Signals, TargetingKv +- `tmp/error.py` — Code, TmpError +- `tmp/identity_match_request.py` — Attestation, Consent, Identity, IdentityMatchRequest, SealedCredential, VerificationLevel +- `tmp/identity_match_response.py` — IdentityMatchResponse +- `tmp/offer.py` — Offer +- `tmp/offer_price.py` — Model, OfferPrice +- `tmp/provider_registration.py` — Country, Status, TmpProviderRegistration, TmpProviderRegistration1, TmpProviderRegistration2 ## Field changes -- `bundled/content_standards/update_content_standards_request.py` - - **classes added**: Disclosure1235, Disclosure1236, Disclosure1237, Disclosure1238, Disclosure1239, EmbeddedProvenanceItem1232, EmbeddedProvenanceItem1233, EmbeddedProvenanceItem1234, EmbeddedProvenanceItem1235, EmbeddedProvenanceItem1236, Provenance1231, Provenance1232, Provenance1233, Provenance1234, Provenance1235, Role1298, VerifyAgent2455, Watermark1232, Watermark1233, Watermark1234, Watermark1235, Watermark1236 - - **classes removed**: Disclosure1226, Disclosure1227, Disclosure1228, Disclosure1229, Disclosure1230, EmbeddedProvenanceItem1223, EmbeddedProvenanceItem1224, EmbeddedProvenanceItem1225, EmbeddedProvenanceItem1226, EmbeddedProvenanceItem1227, Provenance1222, Provenance1223, Provenance1224, Provenance1225, Provenance1226, Role1287, VerifyAgent2445, Watermark1223, Watermark1224, Watermark1225, Watermark1226, Watermark1227 -- `bundled/content_standards/validate_content_delivery_request.py` - - **classes added**: Disclosure1245, Disclosure1246, Disclosure1247, Disclosure1248, EmbeddedProvenanceItem1242, EmbeddedProvenanceItem1243, EmbeddedProvenanceItem1244, EmbeddedProvenanceItem1245, Provenance1241, Provenance1242, Provenance1243, Provenance1244, Role1315, VerifyAgent2483, Watermark1242, Watermark1243, Watermark1244, Watermark1245 - - **classes removed**: Disclosure1240, Disclosure1241, Disclosure1242, Disclosure1243, EmbeddedProvenanceItem1237, EmbeddedProvenanceItem1238, EmbeddedProvenanceItem1239, EmbeddedProvenanceItem1240, Provenance1236, Provenance1237, Provenance1238, Provenance1239, Role1304, VerifyAgent2473, Watermark1237, Watermark1238, Watermark1239, Watermark1240 -- `bundled/core/tasks_get_request.py` - - **classes added**: Account51, VerifyAgent1779 - - **classes removed**: Account45, VerifyAgent1769 -- `bundled/core/tasks_get_response.py` - - **classes added**: Account53, Brand52, Brand53, Brand54, Brand55, Brand56, BrandKitOverride148, BrandKitOverride149, BrandKitOverride150, BrandKitOverride151, BrandKitOverride152, Disclosure1224, Disclosure1225, Disclosure1226, Disclosure1227, Disclosure1228, Disclosure933, EmbeddedProvenanceItem1221, EmbeddedProvenanceItem1222, EmbeddedProvenanceItem1223, EmbeddedProvenanceItem1224, EmbeddedProvenanceItem1225, Jurisdiction1008, Jurisdiction934, Logo149, Logo150, Logo151, Logo152, Logo153, Method62, Provenance1220, Provenance1221, Provenance1222, Provenance1223, Provenance1224, Result1001, Result1003, Result1004, Result1010, Result1103, Result1196, Result1291, Result1303, Result1304, Result1305, Result1306, Result1307, Result931, Result956, Result957, Result982, Result983, Result984, Result991, Result992, Result993, Result994, Role1020, Role991, Status263, Status314, Status315, Status327, Status328, VerifyAgent1781, Watermark1221, Watermark1222, Watermark1223, Watermark1224, Watermark1225 - - **classes removed**: Account47, Brand45, Brand46, Brand47, Brand48, Brand49, BrandKitOverride95, BrandKitOverride96, BrandKitOverride97, BrandKitOverride98, BrandKitOverride99, Disclosure887, Disclosure888, Disclosure889, Disclosure890, Disclosure891, Disclosure938, EmbeddedProvenanceItem886, EmbeddedProvenanceItem887, EmbeddedProvenanceItem888, EmbeddedProvenanceItem889, EmbeddedProvenanceItem890, Jurisdiction923, Jurisdiction997, Logo100, Logo96, Logo97, Logo98, Logo99, Method57, Provenance885, Provenance886, Provenance887, Provenance888, Provenance889, Result1098, Result1191, Result1284, Result1285, Result1286, Result1287, Result1288, Result1296, Result926, Result951, Result952, Result973, Result974, Result977, Result985, Result986, Result987, Result988, Result989, Result996, Result998, Result999, Role1009, Role980, Status255, Status306, Status307, Status319, Status320, VerifyAgent1771, Watermark886, Watermark887, Watermark888, Watermark889, Watermark890 - - `Result1000`: `+adcp_error`, `+adcp_major_version`, `+adcp_version`, `+context_id`, `+governance_context`, `+message`, `+payload`, `+push_notification_config`, `+replayed`, `+status`, `+task_id`, `+timestamp` `-attribution_window`, `-currency`, `-media_buy_deliveries`, `-next_expected_at`, `-notification_type`, `-partial_data`, `-reporting_period`, `-sandbox`, `-sequence_number`, `-unavailable_count` - - `Result1005`: `+attribution_window`, `+errors`, `+media_buy_deliveries`, `+next_expected_at`, `+notification_type`, `+partial_data`, `+reporting_period`, `+sequence_number`, `+unavailable_count` `-adcp_error`, `-adcp_major_version`, `-adcp_version`, `-build_variant_id`, `-consumption`, `-context_id`, `-creative_manifest`, `-expires_at`, `-governance_context`, `-message`, `-payload`, `-preview`, `-preview_error`, `-pricing_option_id`, `-push_notification_config`, `-recipe_hash`, `-replayed`, `-status`, `-task_id`, `-timestamp`, `-vendor_cost` - - `Result1289`: `+adcp_error`, `+adcp_major_version`, `+adcp_version`, `+context_id`, `+estimate`, `+expires_at`, `+governance_context`, `+mode`, `+payload`, `+push_notification_config`, `+replayed`, `+timestamp` `-errors` - - `Result1290`: `+errors` `-creatives`, `-dry_run`, `-sandbox` - - `Result1292`: `+current_step`, `+percentage`, `+step_number`, `+total_steps` `-adcp_error`, `-adcp_major_version`, `-adcp_version`, `-context_id`, `-errors`, `-governance_context`, `-message`, `-payload`, `-push_notification_config`, `-replayed`, `-status`, `-task_id`, `-timestamp` - - `Result1293`: `+reason` `-adcp_error`, `-adcp_major_version`, `-adcp_version`, `-context_id`, `-governance_context`, `-message`, `-payload`, `-push_notification_config`, `-replayed`, `-status`, `-task_id`, `-timestamp` - - `Result1294`: `+errors`, `+message`, `+status`, `+task_id` `-creatives_processed`, `-creatives_total`, `-current_step`, `-percentage`, `-step_number`, `-total_steps` - - `Result1295`: `+adcp_error`, `+adcp_major_version`, `+adcp_version`, `+context_id`, `+creatives`, `+dry_run`, `+governance_context`, `+message`, `+payload`, `+push_notification_config`, `+replayed`, `+sandbox`, `+status`, `+task_id`, `+timestamp` `-reason` - - `Result1297`: `+errors` `-catalogs`, `-dry_run`, `-sandbox` - - `Result1299`: `+creatives_processed`, `+creatives_total`, `+current_step`, `+percentage`, `+step_number`, `+total_steps` `-adcp_error`, `-adcp_major_version`, `-adcp_version`, `-context_id`, `-errors`, `-governance_context`, `-message`, `-payload`, `-push_notification_config`, `-replayed`, `-status`, `-task_id`, `-timestamp` - - `Result1300`: `+reason` `-catalogs_processed`, `-catalogs_total`, `-current_step`, `-items_processed`, `-items_total`, `-percentage`, `-step_number`, `-total_steps` - - `Result1301`: `+errors`, `+message`, `+status`, `+task_id` `-reason` - - `Result1302`: `+adcp_error`, `+adcp_major_version`, `+adcp_version`, `+catalogs`, `+context_id`, `+dry_run`, `+governance_context`, `+payload`, `+push_notification_config`, `+replayed`, `+sandbox`, `+timestamp` `-errors` - - `Result979`: `+cache_scope`, `+errors`, `+incomplete`, `+pagination`, `+pricing_version`, `+signals`, `+unchanged`, `+wholesale_feed_version` `-account`, `-available_actions`, `-confirmed_at`, `-creative_deadline`, `-currency`, `-invoice_recipient`, `-media_buy_id`, `-media_buy_status`, `-packages`, `-planned_delivery`, `-revision`, `-total_budget`, `-valid_actions` - - `Result990`: `+errors` `-affected_packages`, `-available_actions`, `-currency`, `-implementation_date`, `-invoice_recipient`, `-media_buy_id`, `-media_buy_status`, `-revision`, `-sandbox`, `-total_budget`, `-valid_actions` - - `Result995`: `+affected_packages`, `+available_actions`, `+currency`, `+implementation_date`, `+invoice_recipient`, `+media_buy_id`, `+media_buy_status`, `+revision`, `+sandbox`, `+total_budget`, `+valid_actions` `-errors` -- `bundled/core/tasks_list_request.py` - - **classes added**: Account55, VerifyAgent2453 - - **classes removed**: Account49, VerifyAgent2443 -- `bundled/creative/sync_creatives_request.py` - - **classes added**: Account48, Disclosure886, Disclosure887, Disclosure888, Disclosure889, Disclosure890, EmbeddedProvenanceItem884, EmbeddedProvenanceItem885, EmbeddedProvenanceItem886, EmbeddedProvenanceItem887, EmbeddedProvenanceItem888, Jurisdiction838, Provenance883, Provenance884, Provenance885, Provenance886, Provenance887, Role863, Status208, VerifyAgent1597, Watermark884, Watermark885, Watermark886, Watermark887, Watermark888 - - **classes removed**: Account42, Disclosure796, Disclosure797, Disclosure798, Disclosure799, Disclosure800, EmbeddedProvenanceItem794, EmbeddedProvenanceItem795, EmbeddedProvenanceItem796, EmbeddedProvenanceItem797, EmbeddedProvenanceItem798, Jurisdiction827, Provenance793, Provenance794, Provenance795, Provenance796, Provenance797, Role852, Status200, VerifyAgent1587, Watermark794, Watermark795, Watermark796, Watermark797, Watermark798 -- `bundled/creative/validate_input_request.py` - - **classes added**: Account61, Brand63, Brand64, Brand65, BrandKitOverride159, BrandKitOverride160, BrandKitOverride161, Disclosure1338, Disclosure1339, Disclosure1340, Disclosure1341, Disclosure1342, EmbeddedProvenanceItem1335, EmbeddedProvenanceItem1336, EmbeddedProvenanceItem1337, EmbeddedProvenanceItem1338, EmbeddedProvenanceItem1339, Jurisdiction1303, Logo160, Logo161, Logo162, Provenance1334, Provenance1335, Provenance1336, Provenance1337, Provenance1338, Role1336, VerifyAgent2493, Watermark1335, Watermark1336, Watermark1337, Watermark1338, Watermark1339 - - **classes removed**: Account55, Brand58, Brand59, Brand60, BrandKitOverride154, BrandKitOverride155, BrandKitOverride156, Disclosure1245, Disclosure1246, Disclosure1247, Disclosure1248, Disclosure1249, EmbeddedProvenanceItem1242, EmbeddedProvenanceItem1243, EmbeddedProvenanceItem1244, EmbeddedProvenanceItem1245, EmbeddedProvenanceItem1246, Jurisdiction1292, Logo155, Logo156, Logo157, Provenance1241, Provenance1242, Provenance1243, Provenance1244, Provenance1245, Role1325, VerifyAgent2483, Watermark1242, Watermark1243, Watermark1244, Watermark1245, Watermark1246 -- `bundled/media_buy/get_media_buys_response.py` - - `MediaBuy`: `+status_as_of` -- `bundled/property/update_property_list_request.py` - - **classes added**: Account57, Brand59, BrandKitOverride155, Disclosure1241, EmbeddedProvenanceItem1238, Logo156, Provenance1237, VerifyAgent2475, Watermark1238 - - **classes removed**: Account51, Brand54, BrandKitOverride150, Disclosure1236, EmbeddedProvenanceItem1233, Logo151, Provenance1232, VerifyAgent2465, Watermark1233 -- `bundled/property/update_property_list_response.py` - - **classes added**: Account59, Brand61, BrandKitOverride157, Disclosure1243, EmbeddedProvenanceItem1240, Logo158, Provenance1239, VerifyAgent2479, Watermark1240 - - **classes removed**: Account53, Brand56, BrandKitOverride152, Disclosure1238, EmbeddedProvenanceItem1235, Logo153, Provenance1234, VerifyAgent2469, Watermark1235 -- `bundled/property/validate_property_delivery_request.py` - - **classes added**: Account63, VerifyAgent2681 - - **classes removed**: Account57, VerifyAgent2671 -- `bundled/property/validate_property_delivery_response.py` - - **classes added**: Status338, Status339, Status340 - - **classes removed**: Status330, Status331, Status332 -- `bundled/sponsored_intelligence/si_get_offering_response.py` - - **classes added**: Account, AiTool, Brand, BrandKitOverride, C2pa, C2paAction, Colors, ContextUse, DataSubjectContestation, DeclaredBy, DeclaredBy794, DigitalSourceType, Disclosure, DisclosureObligation, EmbeddedProvenanceItem, HumanOversight, Jurisdiction, Jurisdiction827, Logo, MediaType, Method, PayingPrincipal, Persistence, Position, Provenance, Proximity, RenderGuidance, Result, Role, Role838, SponsoredContext, Timing, VerificationItem, VerifyAgent, VerifyAgent1587, Watermark - - `SiGetOfferingResponse`: `+sponsored_context` -- `bundled/sponsored_intelligence/si_initiate_session_request.py` - - **classes added**: Account, AiTool, Brand, BrandKitOverride, C2pa, C2paAction, Colors, DataSubjectContestation, DeclaredBy, DeclaredBy796, DigitalSourceType, Disclosure, DisclosureCommitment, DisclosureObligation, EmbeddedProvenanceItem, HostReceipt, HumanOversight, Jurisdiction, Jurisdiction829, Logo, MediaType, Method, PayingPrincipal, Persistence, Position, Provenance, Proximity, RenderGuidance, Result, Role, Role840, SIContextUse, SponsoredContext, SponsoredContextReceipt, Status, Status198, Timing, VerificationItem, VerifyAgent, VerifyAgent1589, Watermark - - `SiInitiateSessionRequest`: `+sponsored_context_receipt` -- `bundled/sponsored_intelligence/si_initiate_session_response.py` - - **classes added**: Account, AiTool, Brand, BrandKitOverride, C2pa, C2paAction, Colors, ContextUse, DataSubjectContestation, DeclaredBy, DeclaredBy798, DigitalSourceType, Disclosure, DisclosureObligation, EmbeddedProvenanceItem, HumanOversight, Jurisdiction, Jurisdiction831, Logo, MediaType, Method, PayingPrincipal, Persistence, Position, Provenance, Proximity, RenderGuidance, Result, Role, Role842, SponsoredContext, Timing, VerificationItem, VerifyAgent, VerifyAgent1591, Watermark - - `SiInitiateSessionResponse`: `+sponsored_context` -- `bundled/sponsored_intelligence/si_send_message_request.py` - - **classes added**: Account, AiTool, Brand, BrandKitOverride, C2pa, C2paAction, Colors, DataSubjectContestation, DeclaredBy, DeclaredBy800, DigitalSourceType, Disclosure, DisclosureCommitment, DisclosureObligation, EmbeddedProvenanceItem, HostReceipt, HumanOversight, Jurisdiction, Jurisdiction833, Logo, MediaType, Method, PayingPrincipal, Persistence, Position, Provenance, Proximity, RenderGuidance, Result, Role, Role844, SIContextUse, SponsoredContext, SponsoredContextReceipt, Status, Status201, Timing, VerificationItem, VerifyAgent, VerifyAgent1593, Watermark - - `SiSendMessageRequest`: `+sponsored_context_receipt` -- `bundled/sponsored_intelligence/si_send_message_response.py` - - **classes added**: Account, AiTool, Brand, BrandKitOverride, C2pa, C2paAction, Colors, ContextUse, DataSubjectContestation, DeclaredBy, DeclaredBy802, DigitalSourceType, Disclosure, DisclosureObligation, EmbeddedProvenanceItem, HumanOversight, Jurisdiction, Jurisdiction835, Logo, MediaType, Method, PayingPrincipal, Persistence, Position, Provenance, Proximity, RenderGuidance, Result, Role, Role846, SponsoredContext, Timing, VerificationItem, VerifyAgent, VerifyAgent1595, Watermark - - `SiSendMessageResponse`: `+sponsored_context` -- `core/registry_event.py` - - **classes added**: CollectionIdentifier, CollectionPayload, Payload11, Payload12, Payload8, RegistryEvent17, RegistryEvent18, RegistryEvent19, RegistryEvent20, Status - - **classes removed**: Payload10 - - `EntityType`: `+collection` - - `EventType`: `+collection_created`, `+collection_merged`, `+collection_removed`, `+collection_updated` - - `Payload3`: `+alias_rid`, `+canonical_rid`, `+evidence` `-agent_url`, `-removed_from_publishers` - - `Payload4`: `+collection_rid`, `+publisher_domain`, `+status` `-agent_url`, `-changed_fields` - - `Payload5`: `+removed_from_publishers` `-current_status`, `-headline`, `-previous_status`, `-storyboards`, `-storyboards_passing`, `-storyboards_total`, `-tracks` - - `Payload6`: `+changed_fields` `-adcp_version`, `-role`, `-verified_specialisms` - - `Payload7`: `+current_status`, `+headline`, `+previous_status`, `+storyboards`, `+storyboards_passing`, `+storyboards_total`, `+tracks` `-adcp_version`, `-reason`, `-role` - - `Payload9`: `+adcp_version`, `+agent_url`, `+reason`, `+role` `-agents_added`, `-agents_removed`, `-changed_fields`, `-properties_added`, `-properties_removed` - - `PublisherAdagentsPayload`: `+collection_count` -- `core/wholesale_feed_event.py` - - **classes added**: Payload17, Payload24, Payload25 - - **classes removed**: Payload15, Payload16, Payload19 - - `Payload18`: `+changed_fields`, `+product` `-removal_reason` - - `Payload20`: `+product_id`, `+removal_reason` `-changed_fields`, `-signal`, `-signal_agent_segment_id`, `-signal_ref` - - `Payload21`: `+signal` `-effective_at`, `-previous_pricing_option_ids`, `-pricing_options`, `-retracts_event_id` - - `Payload22`: `+changed_fields`, `+signal` `-removal_reason` - - `Payload23`: `+effective_at`, `+previous_pricing_option_ids`, `+pricing_options`, `+retracts_event_id`, `+signal_agent_segment_id`, `+signal_ref` `-affected_count`, `-affected_entity_type`, `-recommendation`, `-summary` -- `enums/distribution_identifier_type.py` - - `DistributionIdentifierType`: `+youtube_channel_handle`, `+youtube_channel_url` -- `governance/sync_plans_response.py` - - **classes added**: Status214 - - **classes removed**: Status206 -- `media_buy/get_media_buys_response.py` - - `MediaBuy`: `+status_as_of` -- `sponsored_intelligence/si_get_offering_response.py` - - `SiGetOfferingResponse`: `+sponsored_context` -- `sponsored_intelligence/si_initiate_session_request.py` - - `SiInitiateSessionRequest`: `+sponsored_context_receipt` -- `sponsored_intelligence/si_initiate_session_response.py` - - `SiInitiateSessionResponse`: `+sponsored_context` -- `sponsored_intelligence/si_send_message_request.py` - - `SiSendMessageRequest`: `+sponsored_context_receipt` -- `sponsored_intelligence/si_send_message_response.py` - - `SiSendMessageResponse`: `+sponsored_context` +- `bundled/protocol/get_adcp_capabilities_response.py` + - `MediaBuy`: `+governance_aware` +- `core/registry_feed_response.py` + - **classes added**: Freshness + - `RegistryFeedResponse`: `+freshness` +- `manifest_schema.py` + - `Protocol`: `+trusted_match` `-tmp` +- `protocol/get_adcp_capabilities_response.py` + - `MediaBuy`: `+governance_aware` diff --git a/schemas/cache/3.1/adagents.json b/schemas/cache/3.1/adagents.json index 4d3e73522..316934eb5 100644 --- a/schemas/cache/3.1/adagents.json +++ b/schemas/cache/3.1/adagents.json @@ -786,12 +786,12 @@ ], "examples": [ { - "$schema": "/schemas/3.1.0/adagents.json", + "$schema": "/schemas/3.1.1/adagents.json", "authoritative_location": "https://cdn.example.com/adagents/v2/adagents.json", "last_updated": "2025-01-15T10:00:00Z" }, { - "$schema": "/schemas/3.1.0/adagents.json", + "$schema": "/schemas/3.1.1/adagents.json", "properties": [ { "property_id": "example_site", @@ -872,7 +872,7 @@ "last_updated": "2025-01-10T12:00:00Z" }, { - "$schema": "/schemas/3.1.0/adagents.json", + "$schema": "/schemas/3.1.1/adagents.json", "contact": { "name": "Meta Advertising Operations", "email": "adops@meta.com", @@ -981,7 +981,7 @@ "last_updated": "2025-01-10T15:30:00Z" }, { - "$schema": "/schemas/3.1.0/adagents.json", + "$schema": "/schemas/3.1.1/adagents.json", "contact": { "name": "Tumblr Advertising" }, @@ -1020,7 +1020,7 @@ "last_updated": "2025-01-10T16:00:00Z" }, { - "$schema": "/schemas/3.1.0/adagents.json", + "$schema": "/schemas/3.1.1/adagents.json", "contact": { "name": "Example Third-Party Sales Agent", "email": "sales@agent.example", @@ -1085,7 +1085,7 @@ "last_updated": "2025-01-10T17:00:00Z" }, { - "$schema": "/schemas/3.1.0/adagents.json", + "$schema": "/schemas/3.1.1/adagents.json", "contact": { "name": "Premium News Publisher", "email": "adops@news.example.com", @@ -1160,7 +1160,7 @@ "last_updated": "2025-01-10T18:00:00Z" }, { - "$schema": "/schemas/3.1.0/adagents.json", + "$schema": "/schemas/3.1.1/adagents.json", "contact": { "name": "Polk Automotive Data", "email": "partnerships@polk.com", diff --git a/schemas/cache/3.1/brand.json b/schemas/cache/3.1/brand.json index 25c5ec481..547f29cca 100644 --- a/schemas/cache/3.1/brand.json +++ b/schemas/cache/3.1/brand.json @@ -2720,16 +2720,16 @@ ], "examples": [ { - "$schema": "/schemas/3.1.0/brand.json", + "$schema": "/schemas/3.1.1/brand.json", "authoritative_location": "https://adcontextprotocol.org/brand/abc123/brand.json" }, { - "$schema": "/schemas/3.1.0/brand.json", + "$schema": "/schemas/3.1.1/brand.json", "house": "nikeinc.com", "note": "Redirect to house domain for full brand portfolio" }, { - "$schema": "/schemas/3.1.0/brand.json", + "$schema": "/schemas/3.1.1/brand.json", "version": "1.0", "agents": [ { @@ -2740,7 +2740,7 @@ ] }, { - "$schema": "/schemas/3.1.0/brand.json", + "$schema": "/schemas/3.1.1/brand.json", "version": "1.0", "house": { "domain": "pg.com", @@ -3041,7 +3041,7 @@ "last_updated": "2026-01-15T10:00:00Z" }, { - "$schema": "/schemas/3.1.0/brand.json", + "$schema": "/schemas/3.1.1/brand.json", "version": "1.0", "house": { "domain": "nikeinc.com", @@ -3222,7 +3222,7 @@ "last_updated": "2026-01-15T10:00:00Z" }, { - "$schema": "/schemas/3.1.0/brand.json", + "$schema": "/schemas/3.1.1/brand.json", "version": "1.0", "house": { "domain": "mediavine.com", @@ -3273,7 +3273,7 @@ "last_updated": "2026-01-15T10:00:00Z" }, { - "$schema": "/schemas/3.1.0/brand.json", + "$schema": "/schemas/3.1.1/brand.json", "version": "1.0", "house": { "domain": "nikeinc.com", @@ -3310,7 +3310,7 @@ "last_updated": "2026-01-15T10:00:00Z" }, { - "$schema": "/schemas/3.1.0/brand.json", + "$schema": "/schemas/3.1.1/brand.json", "version": "1.0", "house": { "domain": "wpp.com", @@ -3335,7 +3335,7 @@ "last_updated": "2026-01-15T10:00:00Z" }, { - "$schema": "/schemas/3.1.0/brand.json", + "$schema": "/schemas/3.1.1/brand.json", "version": "1.0", "id": "converse", "names": [ @@ -3355,7 +3355,7 @@ "last_updated": "2026-01-15T10:00:00Z" }, { - "$schema": "/schemas/3.1.0/brand.json", + "$schema": "/schemas/3.1.1/brand.json", "version": "1.0", "id": "patagonia", "names": [ diff --git a/schemas/cache/3.1/bundled/content-standards/calibrate-content-request.json b/schemas/cache/3.1/bundled/content-standards/calibrate-content-request.json index 79f712b18..682a41378 100644 --- a/schemas/cache/3.1/bundled/content-standards/calibrate-content-request.json +++ b/schemas/cache/3.1/bundled/content-standards/calibrate-content-request.json @@ -2279,7 +2279,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:16:59.924Z", + "generatedAt": "2026-06-30T19:14:39.361Z", "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/3.1/bundled/content-standards/calibrate-content-response.json b/schemas/cache/3.1/bundled/content-standards/calibrate-content-response.json index 69e8208de..524f05d8a 100644 --- a/schemas/cache/3.1/bundled/content-standards/calibrate-content-response.json +++ b/schemas/cache/3.1/bundled/content-standards/calibrate-content-response.json @@ -667,7 +667,7 @@ ], "properties": {}, "_bundled": { - "generatedAt": "2026-06-18T08:16:59.927Z", + "generatedAt": "2026-06-30T19:14:39.364Z", "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/3.1/bundled/content-standards/create-content-standards-request.json b/schemas/cache/3.1/bundled/content-standards/create-content-standards-request.json index e6c0255b8..be1a75508 100644 --- a/schemas/cache/3.1/bundled/content-standards/create-content-standards-request.json +++ b/schemas/cache/3.1/bundled/content-standards/create-content-standards-request.json @@ -4697,7 +4697,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:16:59.941Z", + "generatedAt": "2026-06-30T19:14:39.377Z", "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/3.1/bundled/content-standards/create-content-standards-response.json b/schemas/cache/3.1/bundled/content-standards/create-content-standards-response.json index b9654eb75..61d428824 100644 --- a/schemas/cache/3.1/bundled/content-standards/create-content-standards-response.json +++ b/schemas/cache/3.1/bundled/content-standards/create-content-standards-response.json @@ -603,7 +603,7 @@ ], "properties": {}, "_bundled": { - "generatedAt": "2026-06-18T08:16:59.949Z", + "generatedAt": "2026-06-30T19:14:39.379Z", "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/3.1/bundled/content-standards/get-content-standards-request.json b/schemas/cache/3.1/bundled/content-standards/get-content-standards-request.json index a27a102be..708aa8cfa 100644 --- a/schemas/cache/3.1/bundled/content-standards/get-content-standards-request.json +++ b/schemas/cache/3.1/bundled/content-standards/get-content-standards-request.json @@ -51,7 +51,7 @@ "standards_id" ], "_bundled": { - "generatedAt": "2026-06-18T08:16:59.950Z", + "generatedAt": "2026-06-30T19:14:39.379Z", "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/3.1/bundled/content-standards/get-content-standards-response.json b/schemas/cache/3.1/bundled/content-standards/get-content-standards-response.json index cfca23932..71990c700 100644 --- a/schemas/cache/3.1/bundled/content-standards/get-content-standards-response.json +++ b/schemas/cache/3.1/bundled/content-standards/get-content-standards-response.json @@ -5454,7 +5454,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:16:59.963Z", + "generatedAt": "2026-06-30T19:14:39.397Z", "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/3.1/bundled/content-standards/get-media-buy-artifacts-request.json b/schemas/cache/3.1/bundled/content-standards/get-media-buy-artifacts-request.json index db7f954dd..61b411714 100644 --- a/schemas/cache/3.1/bundled/content-standards/get-media-buy-artifacts-request.json +++ b/schemas/cache/3.1/bundled/content-standards/get-media-buy-artifacts-request.json @@ -743,7 +743,7 @@ "media_buy_id" ], "_bundled": { - "generatedAt": "2026-06-18T08:16:59.970Z", + "generatedAt": "2026-06-30T19:14:39.401Z", "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/3.1/bundled/content-standards/get-media-buy-artifacts-response.json b/schemas/cache/3.1/bundled/content-standards/get-media-buy-artifacts-response.json index 83040e3c4..02b7ee561 100644 --- a/schemas/cache/3.1/bundled/content-standards/get-media-buy-artifacts-response.json +++ b/schemas/cache/3.1/bundled/content-standards/get-media-buy-artifacts-response.json @@ -2921,7 +2921,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:16:59.974Z", + "generatedAt": "2026-06-30T19:14:39.405Z", "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/3.1/bundled/content-standards/list-content-standards-request.json b/schemas/cache/3.1/bundled/content-standards/list-content-standards-request.json index 1efde0186..bd64b6a8b 100644 --- a/schemas/cache/3.1/bundled/content-standards/list-content-standards-request.json +++ b/schemas/cache/3.1/bundled/content-standards/list-content-standards-request.json @@ -134,7 +134,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:16:59.976Z", + "generatedAt": "2026-06-30T19:14:39.406Z", "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/3.1/bundled/content-standards/list-content-standards-response.json b/schemas/cache/3.1/bundled/content-standards/list-content-standards-response.json index 8eaf845cb..0a44c942d 100644 --- a/schemas/cache/3.1/bundled/content-standards/list-content-standards-response.json +++ b/schemas/cache/3.1/bundled/content-standards/list-content-standards-response.json @@ -5483,7 +5483,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:16:59.983Z", + "generatedAt": "2026-06-30T19:14:39.422Z", "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/3.1/bundled/content-standards/update-content-standards-request.json b/schemas/cache/3.1/bundled/content-standards/update-content-standards-request.json index 91de84fac..03c6a10ce 100644 --- a/schemas/cache/3.1/bundled/content-standards/update-content-standards-request.json +++ b/schemas/cache/3.1/bundled/content-standards/update-content-standards-request.json @@ -4686,7 +4686,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:16:59.990Z", + "generatedAt": "2026-06-30T19:14:39.428Z", "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/3.1/bundled/content-standards/update-content-standards-response.json b/schemas/cache/3.1/bundled/content-standards/update-content-standards-response.json index 68ad68af9..ed0b56871 100644 --- a/schemas/cache/3.1/bundled/content-standards/update-content-standards-response.json +++ b/schemas/cache/3.1/bundled/content-standards/update-content-standards-response.json @@ -618,7 +618,7 @@ ], "properties": {}, "_bundled": { - "generatedAt": "2026-06-18T08:16:59.992Z", + "generatedAt": "2026-06-30T19:14:39.430Z", "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/3.1/bundled/content-standards/validate-content-delivery-request.json b/schemas/cache/3.1/bundled/content-standards/validate-content-delivery-request.json index b746cc923..735734340 100644 --- a/schemas/cache/3.1/bundled/content-standards/validate-content-delivery-request.json +++ b/schemas/cache/3.1/bundled/content-standards/validate-content-delivery-request.json @@ -2333,7 +2333,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:16:59.995Z", + "generatedAt": "2026-06-30T19:14:39.432Z", "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/3.1/bundled/content-standards/validate-content-delivery-response.json b/schemas/cache/3.1/bundled/content-standards/validate-content-delivery-response.json index d657ada55..47f643a5d 100644 --- a/schemas/cache/3.1/bundled/content-standards/validate-content-delivery-response.json +++ b/schemas/cache/3.1/bundled/content-standards/validate-content-delivery-response.json @@ -695,7 +695,7 @@ ], "properties": {}, "_bundled": { - "generatedAt": "2026-06-18T08:16:59.997Z", + "generatedAt": "2026-06-30T19:14:39.434Z", "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/3.1/bundled/core/tasks-get-request.json b/schemas/cache/3.1/bundled/core/tasks-get-request.json index dc28c024f..e043e34be 100644 --- a/schemas/cache/3.1/bundled/core/tasks-get-request.json +++ b/schemas/cache/3.1/bundled/core/tasks-get-request.json @@ -737,7 +737,7 @@ } ], "_bundled": { - "generatedAt": "2026-06-18T08:16:59.999Z", + "generatedAt": "2026-06-30T19:14:39.436Z", "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/3.1/bundled/core/tasks-get-response.json b/schemas/cache/3.1/bundled/core/tasks-get-response.json index e580c7086..c8cfb4426 100644 --- a/schemas/cache/3.1/bundled/core/tasks-get-response.json +++ b/schemas/cache/3.1/bundled/core/tasks-get-response.json @@ -36164,7 +36164,7 @@ }, "pagination": { "title": "Pagination Response", - "description": "Standard cursor-based pagination metadata for list responses", + "description": "Cursor metadata for paginated get_products responses. In brief/refine mode, continuation pages bound returned products[] for the seller's curated or refined answer; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope, and pagination does not convert the response into an exhaustive feed contract. In wholesale mode, continuation pages walk the wholesale product feed.", "type": "object", "properties": { "has_more": { @@ -92604,7 +92604,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -92620,12 +92621,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -93525,7 +93526,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -98511,7 +98512,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -98527,12 +98529,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -101453,7 +101455,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -101469,12 +101472,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -102374,7 +102377,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -107360,7 +107363,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -107376,12 +107380,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -111946,7 +111950,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -111962,12 +111967,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -112867,7 +112872,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -117853,7 +117858,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -117869,12 +117875,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -120795,7 +120801,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -120811,12 +120818,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -121716,7 +121723,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -126702,7 +126709,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -126718,12 +126726,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -132169,7 +132177,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -132185,12 +132194,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -133090,7 +133099,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -138076,7 +138085,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -138092,12 +138102,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -141018,7 +141028,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -141034,12 +141045,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -141939,7 +141950,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -146925,7 +146936,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -146941,12 +146953,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -156018,7 +156030,7 @@ ], "enumDescriptions": { "guaranteed": "Reserved inventory with guaranteed delivery", - "non_guaranteed": "Auction-based inventory without delivery guarantees" + "non_guaranteed": "Inventory without reserved or guaranteed delivery, commonly auction-based or otherwise best-effort. Do not use for scheduled broadcast buys solely because final audience delivery is estimated from historical ranges or settles through third-party measurement." } }, "Exclusivity": { @@ -157995,7 +158007,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.262Z", + "generatedAt": "2026-06-30T19:14:39.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/3.1/bundled/core/tasks-list-request.json b/schemas/cache/3.1/bundled/core/tasks-list-request.json index 97c269ed4..b8c1c6e24 100644 --- a/schemas/cache/3.1/bundled/core/tasks-list-request.json +++ b/schemas/cache/3.1/bundled/core/tasks-list-request.json @@ -993,7 +993,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.327Z", + "generatedAt": "2026-06-30T19:14:39.747Z", "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/3.1/bundled/core/tasks-list-response.json b/schemas/cache/3.1/bundled/core/tasks-list-response.json index 165f0bb3c..8cecfec0c 100644 --- a/schemas/cache/3.1/bundled/core/tasks-list-response.json +++ b/schemas/cache/3.1/bundled/core/tasks-list-response.json @@ -665,7 +665,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.328Z", + "generatedAt": "2026-06-30T19:14:39.749Z", "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/3.1/bundled/creative/get-creative-delivery-request.json b/schemas/cache/3.1/bundled/creative/get-creative-delivery-request.json index 7066489a3..7a9b41b9e 100644 --- a/schemas/cache/3.1/bundled/creative/get-creative-delivery-request.json +++ b/schemas/cache/3.1/bundled/creative/get-creative-delivery-request.json @@ -754,7 +754,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.329Z", + "generatedAt": "2026-06-30T19:14:39.749Z", "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/3.1/bundled/creative/get-creative-delivery-response.json b/schemas/cache/3.1/bundled/creative/get-creative-delivery-response.json index 4377179ea..31edc2d81 100644 --- a/schemas/cache/3.1/bundled/creative/get-creative-delivery-response.json +++ b/schemas/cache/3.1/bundled/creative/get-creative-delivery-response.json @@ -4162,7 +4162,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -4178,12 +4179,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -5083,7 +5084,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -10069,7 +10070,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -10085,12 +10087,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -13011,7 +13013,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -13027,12 +13030,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -13932,7 +13935,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -18918,7 +18921,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -18934,12 +18938,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -23554,7 +23558,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.363Z", + "generatedAt": "2026-06-30T19:14:39.774Z", "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/3.1/bundled/creative/get-creative-features-request.json b/schemas/cache/3.1/bundled/creative/get-creative-features-request.json index 01f2edbc2..cb199559c 100644 --- a/schemas/cache/3.1/bundled/creative/get-creative-features-request.json +++ b/schemas/cache/3.1/bundled/creative/get-creative-features-request.json @@ -554,7 +554,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -570,12 +571,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -1475,7 +1476,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -6461,7 +6462,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -6477,12 +6479,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -9403,7 +9405,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -9419,12 +9422,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -10324,7 +10327,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -15310,7 +15313,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -15326,12 +15330,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -20166,7 +20170,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.397Z", + "generatedAt": "2026-06-30T19:14:39.797Z", "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/3.1/bundled/creative/get-creative-features-response.json b/schemas/cache/3.1/bundled/creative/get-creative-features-response.json index beb46c5d1..eeb548bfd 100644 --- a/schemas/cache/3.1/bundled/creative/get-creative-features-response.json +++ b/schemas/cache/3.1/bundled/creative/get-creative-features-response.json @@ -836,7 +836,7 @@ ], "properties": {}, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.404Z", + "generatedAt": "2026-06-30T19:14:39.801Z", "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/3.1/bundled/creative/list-creative-formats-request.json b/schemas/cache/3.1/bundled/creative/list-creative-formats-request.json index eaceabed1..538cdfd64 100644 --- a/schemas/cache/3.1/bundled/creative/list-creative-formats-request.json +++ b/schemas/cache/3.1/bundled/creative/list-creative-formats-request.json @@ -988,7 +988,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.406Z", + "generatedAt": "2026-06-30T19:14:39.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/3.1/bundled/creative/list-creative-formats-response.json b/schemas/cache/3.1/bundled/creative/list-creative-formats-response.json index d97231880..89f05bf2b 100644 --- a/schemas/cache/3.1/bundled/creative/list-creative-formats-response.json +++ b/schemas/cache/3.1/bundled/creative/list-creative-formats-response.json @@ -13645,7 +13645,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.421Z", + "generatedAt": "2026-06-30T19:14:39.811Z", "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/3.1/bundled/creative/list-creatives-request.json b/schemas/cache/3.1/bundled/creative/list-creatives-request.json index 1686a9383..f1528f69f 100644 --- a/schemas/cache/3.1/bundled/creative/list-creatives-request.json +++ b/schemas/cache/3.1/bundled/creative/list-creatives-request.json @@ -1666,7 +1666,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.430Z", + "generatedAt": "2026-06-30T19:14:39.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/3.1/bundled/creative/list-creatives-response.json b/schemas/cache/3.1/bundled/creative/list-creatives-response.json index c63c29ece..9bfcc2b3f 100644 --- a/schemas/cache/3.1/bundled/creative/list-creatives-response.json +++ b/schemas/cache/3.1/bundled/creative/list-creatives-response.json @@ -2206,7 +2206,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -2222,12 +2223,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -3127,7 +3128,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -8113,7 +8114,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -8129,12 +8131,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -11055,7 +11057,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -11071,12 +11074,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -11976,7 +11979,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -16962,7 +16965,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -16978,12 +16982,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -21301,7 +21305,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.453Z", + "generatedAt": "2026-06-30T19:14:39.833Z", "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/3.1/bundled/creative/list-transformers-request.json b/schemas/cache/3.1/bundled/creative/list-transformers-request.json index a617b607b..92e967138 100644 --- a/schemas/cache/3.1/bundled/creative/list-transformers-request.json +++ b/schemas/cache/3.1/bundled/creative/list-transformers-request.json @@ -887,7 +887,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.461Z", + "generatedAt": "2026-06-30T19:14:39.838Z", "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/3.1/bundled/creative/list-transformers-response.json b/schemas/cache/3.1/bundled/creative/list-transformers-response.json index 61cae5753..628035242 100644 --- a/schemas/cache/3.1/bundled/creative/list-transformers-response.json +++ b/schemas/cache/3.1/bundled/creative/list-transformers-response.json @@ -1413,7 +1413,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.463Z", + "generatedAt": "2026-06-30T19:14:39.839Z", "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/3.1/bundled/creative/preview-creative-request.json b/schemas/cache/3.1/bundled/creative/preview-creative-request.json index 35a843ece..8feb8e01a 100644 --- a/schemas/cache/3.1/bundled/creative/preview-creative-request.json +++ b/schemas/cache/3.1/bundled/creative/preview-creative-request.json @@ -588,7 +588,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -604,12 +605,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -1509,7 +1510,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -6495,7 +6496,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -6511,12 +6513,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -9437,7 +9439,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -9453,12 +9456,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -10358,7 +10361,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -15344,7 +15347,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -15360,12 +15364,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -19567,7 +19571,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -19583,12 +19588,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -20488,7 +20493,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -25474,7 +25479,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -25490,12 +25496,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -28416,7 +28422,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -28432,12 +28439,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -29337,7 +29344,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -34323,7 +34330,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -34339,12 +34347,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -38722,7 +38730,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.503Z", + "generatedAt": "2026-06-30T19:14:39.874Z", "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/3.1/bundled/creative/preview-creative-response.json b/schemas/cache/3.1/bundled/creative/preview-creative-response.json index 13ef767a8..5d8da5f0a 100644 --- a/schemas/cache/3.1/bundled/creative/preview-creative-response.json +++ b/schemas/cache/3.1/bundled/creative/preview-creative-response.json @@ -2025,7 +2025,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -2041,12 +2042,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -2946,7 +2947,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -7932,7 +7933,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -7948,12 +7950,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -10874,7 +10876,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -10890,12 +10893,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -11795,7 +11798,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -16781,7 +16784,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -16797,12 +16801,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -21076,7 +21080,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.538Z", + "generatedAt": "2026-06-30T19:14:39.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/3.1/bundled/creative/sync-creatives-request.json b/schemas/cache/3.1/bundled/creative/sync-creatives-request.json index 707cc5542..2d48bb2fb 100644 --- a/schemas/cache/3.1/bundled/creative/sync-creatives-request.json +++ b/schemas/cache/3.1/bundled/creative/sync-creatives-request.json @@ -1130,7 +1130,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -1146,12 +1147,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -2051,7 +2052,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -7037,7 +7038,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -7053,12 +7055,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -9979,7 +9981,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -9995,12 +9998,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -10900,7 +10903,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -15886,7 +15889,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -15902,12 +15906,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -19881,7 +19885,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.565Z", + "generatedAt": "2026-06-30T19:14:39.924Z", "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/3.1/bundled/creative/sync-creatives-response.json b/schemas/cache/3.1/bundled/creative/sync-creatives-response.json index 063249bb8..1c8bf8487 100644 --- a/schemas/cache/3.1/bundled/creative/sync-creatives-response.json +++ b/schemas/cache/3.1/bundled/creative/sync-creatives-response.json @@ -2448,7 +2448,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.573Z", + "generatedAt": "2026-06-30T19:14:39.932Z", "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/3.1/bundled/creative/validate-input-request.json b/schemas/cache/3.1/bundled/creative/validate-input-request.json index da33512ec..a48eed64c 100644 --- a/schemas/cache/3.1/bundled/creative/validate-input-request.json +++ b/schemas/cache/3.1/bundled/creative/validate-input-request.json @@ -1592,7 +1592,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -1608,12 +1609,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -2513,7 +2514,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -7499,7 +7500,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -7515,12 +7517,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -10441,7 +10443,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -10457,12 +10460,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -11362,7 +11365,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -16348,7 +16351,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -16364,12 +16368,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -20720,7 +20724,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.595Z", + "generatedAt": "2026-06-30T19:14:39.961Z", "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/3.1/bundled/creative/validate-input-response.json b/schemas/cache/3.1/bundled/creative/validate-input-response.json index 360f8e462..8826c65d0 100644 --- a/schemas/cache/3.1/bundled/creative/validate-input-response.json +++ b/schemas/cache/3.1/bundled/creative/validate-input-response.json @@ -592,7 +592,7 @@ } ], "_bundled": { - "generatedAt": "2026-06-18T08:17:00.602Z", + "generatedAt": "2026-06-30T19:14:39.972Z", "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/3.1/bundled/media-buy/build-creative-request.json b/schemas/cache/3.1/bundled/media-buy/build-creative-request.json index c4e8abac2..5f2576ffb 100644 --- a/schemas/cache/3.1/bundled/media-buy/build-creative-request.json +++ b/schemas/cache/3.1/bundled/media-buy/build-creative-request.json @@ -577,7 +577,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -593,12 +594,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -1498,7 +1499,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -6484,7 +6485,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -6500,12 +6502,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -9426,7 +9428,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -9442,12 +9445,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -10347,7 +10350,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -15333,7 +15336,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -15349,12 +15353,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -26220,7 +26224,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.630Z", + "generatedAt": "2026-06-30T19:14:40.022Z", "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/3.1/bundled/media-buy/build-creative-response.json b/schemas/cache/3.1/bundled/media-buy/build-creative-response.json index 2236590bb..54d33f2fa 100644 --- a/schemas/cache/3.1/bundled/media-buy/build-creative-response.json +++ b/schemas/cache/3.1/bundled/media-buy/build-creative-response.json @@ -935,7 +935,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -951,12 +952,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -1856,7 +1857,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -6842,7 +6843,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -6858,12 +6860,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -9784,7 +9786,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -9800,12 +9803,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -10705,7 +10708,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -15691,7 +15694,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -15707,12 +15711,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -20277,7 +20281,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -20293,12 +20298,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -21198,7 +21203,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -26184,7 +26189,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -26200,12 +26206,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -29126,7 +29132,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -29142,12 +29149,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -30047,7 +30054,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -35033,7 +35040,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -35049,12 +35057,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -40500,7 +40508,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -40516,12 +40525,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -41421,7 +41430,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -46407,7 +46416,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -46423,12 +46433,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -49349,7 +49359,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -49365,12 +49376,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -50270,7 +50281,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -55256,7 +55267,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -55272,12 +55284,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -60667,7 +60679,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.728Z", + "generatedAt": "2026-06-30T19:14:40.120Z", "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/3.1/bundled/media-buy/create-media-buy-request.json b/schemas/cache/3.1/bundled/media-buy/create-media-buy-request.json index 474bb2648..6810271e0 100644 --- a/schemas/cache/3.1/bundled/media-buy/create-media-buy-request.json +++ b/schemas/cache/3.1/bundled/media-buy/create-media-buy-request.json @@ -7197,7 +7197,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -7213,12 +7214,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -8118,7 +8119,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -13104,7 +13105,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -13120,12 +13122,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -16046,7 +16048,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -16062,12 +16065,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -16967,7 +16970,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -21953,7 +21956,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -21969,12 +21973,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -27054,7 +27058,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.780Z", + "generatedAt": "2026-06-30T19:14:40.160Z", "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/3.1/bundled/media-buy/create-media-buy-response.json b/schemas/cache/3.1/bundled/media-buy/create-media-buy-response.json index 818e5ddcc..cb9652a2d 100644 --- a/schemas/cache/3.1/bundled/media-buy/create-media-buy-response.json +++ b/schemas/cache/3.1/bundled/media-buy/create-media-buy-response.json @@ -10489,7 +10489,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.800Z", + "generatedAt": "2026-06-30T19:14:40.179Z", "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/3.1/bundled/media-buy/get-media-buy-delivery-request.json b/schemas/cache/3.1/bundled/media-buy/get-media-buy-delivery-request.json index 05c0d89d6..7a5c234e2 100644 --- a/schemas/cache/3.1/bundled/media-buy/get-media-buy-delivery-request.json +++ b/schemas/cache/3.1/bundled/media-buy/get-media-buy-delivery-request.json @@ -1332,7 +1332,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.804Z", + "generatedAt": "2026-06-30T19:14:40.182Z", "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/3.1/bundled/media-buy/get-media-buy-delivery-response.json b/schemas/cache/3.1/bundled/media-buy/get-media-buy-delivery-response.json index 57b9626e9..eb53bddff 100644 --- a/schemas/cache/3.1/bundled/media-buy/get-media-buy-delivery-response.json +++ b/schemas/cache/3.1/bundled/media-buy/get-media-buy-delivery-response.json @@ -22082,7 +22082,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.826Z", + "generatedAt": "2026-06-30T19:14:40.200Z", "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/3.1/bundled/media-buy/get-media-buys-request.json b/schemas/cache/3.1/bundled/media-buy/get-media-buys-request.json index acd3e0544..645bb307f 100644 --- a/schemas/cache/3.1/bundled/media-buy/get-media-buys-request.json +++ b/schemas/cache/3.1/bundled/media-buy/get-media-buys-request.json @@ -782,7 +782,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.834Z", + "generatedAt": "2026-06-30T19:14:40.205Z", "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/3.1/bundled/media-buy/get-media-buys-response.json b/schemas/cache/3.1/bundled/media-buy/get-media-buys-response.json index d0135f4f7..191613f2e 100644 --- a/schemas/cache/3.1/bundled/media-buy/get-media-buys-response.json +++ b/schemas/cache/3.1/bundled/media-buy/get-media-buys-response.json @@ -6142,7 +6142,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.841Z", + "generatedAt": "2026-06-30T19:14:40.210Z", "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/3.1/bundled/media-buy/get-products-request.json b/schemas/cache/3.1/bundled/media-buy/get-products-request.json index a2f187923..31f56a447 100644 --- a/schemas/cache/3.1/bundled/media-buy/get-products-request.json +++ b/schemas/cache/3.1/bundled/media-buy/get-products-request.json @@ -5083,7 +5083,7 @@ }, "pagination": { "title": "Pagination Request", - "description": "Standard cursor-based pagination parameters for list operations", + "description": "Cursor-based pagination controls for get_products. Valid in all buying modes. In brief mode, pagination bounds the seller's returned products[] for the curated answer to the brief and is not an exhaustive catalog-enumeration contract. In refine mode, pagination bounds the refined products[] result implied by refine[] and filters; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope. In wholesale mode, pagination walks the wholesale product feed and may be combined with wholesale feed versioning.", "type": "object", "properties": { "max_results": { @@ -5251,7 +5251,7 @@ ], "enumDescriptions": { "guaranteed": "Reserved inventory with guaranteed delivery", - "non_guaranteed": "Auction-based inventory without delivery guarantees" + "non_guaranteed": "Inventory without reserved or guaranteed delivery, commonly auction-based or otherwise best-effort. Do not use for scheduled broadcast buys solely because final audience delivery is estimated from historical ranges or settles through third-party measurement." } }, "MetroAreaSystem": { @@ -5317,7 +5317,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.848Z", + "generatedAt": "2026-06-30T19:14:40.217Z", "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/3.1/bundled/media-buy/get-products-response.json b/schemas/cache/3.1/bundled/media-buy/get-products-response.json index 64640702a..e42892a61 100644 --- a/schemas/cache/3.1/bundled/media-buy/get-products-response.json +++ b/schemas/cache/3.1/bundled/media-buy/get-products-response.json @@ -18288,7 +18288,7 @@ ], "enumDescriptions": { "guaranteed": "Reserved inventory with guaranteed delivery", - "non_guaranteed": "Auction-based inventory without delivery guarantees" + "non_guaranteed": "Inventory without reserved or guaranteed delivery, commonly auction-based or otherwise best-effort. Do not use for scheduled broadcast buys solely because final audience delivery is estimated from historical ranges or settles through third-party measurement." } }, "exclusivity": { @@ -36168,7 +36168,7 @@ }, "pagination": { "title": "Pagination Response", - "description": "Standard cursor-based pagination metadata for list responses", + "description": "Cursor metadata for paginated get_products responses. In brief/refine mode, continuation pages bound returned products[] for the seller's curated or refined answer; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope, and pagination does not convert the response into an exhaustive feed contract. In wholesale mode, continuation pages walk the wholesale product feed.", "type": "object", "properties": { "has_more": { @@ -36964,7 +36964,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.888Z", + "generatedAt": "2026-06-30T19:14:40.246Z", "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/3.1/bundled/media-buy/list-creative-formats-request.json b/schemas/cache/3.1/bundled/media-buy/list-creative-formats-request.json index 4fa6fcfda..9577916bd 100644 --- a/schemas/cache/3.1/bundled/media-buy/list-creative-formats-request.json +++ b/schemas/cache/3.1/bundled/media-buy/list-creative-formats-request.json @@ -343,7 +343,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.900Z", + "generatedAt": "2026-06-30T19:14:40.253Z", "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/3.1/bundled/media-buy/list-creative-formats-response.json b/schemas/cache/3.1/bundled/media-buy/list-creative-formats-response.json index d41d5f609..a695604c1 100644 --- a/schemas/cache/3.1/bundled/media-buy/list-creative-formats-response.json +++ b/schemas/cache/3.1/bundled/media-buy/list-creative-formats-response.json @@ -13658,7 +13658,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.913Z", + "generatedAt": "2026-06-30T19:14:40.262Z", "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/3.1/bundled/media-buy/log-event-request.json b/schemas/cache/3.1/bundled/media-buy/log-event-request.json index f84f170ed..678ede418 100644 --- a/schemas/cache/3.1/bundled/media-buy/log-event-request.json +++ b/schemas/cache/3.1/bundled/media-buy/log-event-request.json @@ -627,7 +627,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.919Z", + "generatedAt": "2026-06-30T19:14:40.265Z", "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/3.1/bundled/media-buy/log-event-response.json b/schemas/cache/3.1/bundled/media-buy/log-event-response.json index 7e2719b1d..0d1582aff 100644 --- a/schemas/cache/3.1/bundled/media-buy/log-event-response.json +++ b/schemas/cache/3.1/bundled/media-buy/log-event-response.json @@ -680,7 +680,7 @@ ], "properties": {}, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.920Z", + "generatedAt": "2026-06-30T19:14:40.266Z", "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/3.1/bundled/media-buy/package-request.json b/schemas/cache/3.1/bundled/media-buy/package-request.json index 43891c2d4..07ada0143 100644 --- a/schemas/cache/3.1/bundled/media-buy/package-request.json +++ b/schemas/cache/3.1/bundled/media-buy/package-request.json @@ -6603,7 +6603,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -6619,12 +6620,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -7524,7 +7525,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -12510,7 +12511,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -12526,12 +12528,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -15452,7 +15454,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -15468,12 +15471,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -16373,7 +16376,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -21359,7 +21362,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -21375,12 +21379,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -25246,7 +25250,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.944Z", + "generatedAt": "2026-06-30T19:14:40.292Z", "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/3.1/bundled/media-buy/provide-performance-feedback-request.json b/schemas/cache/3.1/bundled/media-buy/provide-performance-feedback-request.json index 9c7614084..3bb82890f 100644 --- a/schemas/cache/3.1/bundled/media-buy/provide-performance-feedback-request.json +++ b/schemas/cache/3.1/bundled/media-buy/provide-performance-feedback-request.json @@ -132,7 +132,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.953Z", + "generatedAt": "2026-06-30T19:14:40.297Z", "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/3.1/bundled/media-buy/provide-performance-feedback-response.json b/schemas/cache/3.1/bundled/media-buy/provide-performance-feedback-response.json index e178eaeaa..a41444cfd 100644 --- a/schemas/cache/3.1/bundled/media-buy/provide-performance-feedback-response.json +++ b/schemas/cache/3.1/bundled/media-buy/provide-performance-feedback-response.json @@ -629,7 +629,7 @@ ], "properties": {}, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.954Z", + "generatedAt": "2026-06-30T19:14:40.298Z", "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/3.1/bundled/media-buy/sync-audiences-request.json b/schemas/cache/3.1/bundled/media-buy/sync-audiences-request.json index 42f13b9e6..5c9811eab 100644 --- a/schemas/cache/3.1/bundled/media-buy/sync-audiences-request.json +++ b/schemas/cache/3.1/bundled/media-buy/sync-audiences-request.json @@ -965,7 +965,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.956Z", + "generatedAt": "2026-06-30T19:14:40.299Z", "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/3.1/bundled/media-buy/sync-audiences-response.json b/schemas/cache/3.1/bundled/media-buy/sync-audiences-response.json index 3e7737540..4bd2e84cb 100644 --- a/schemas/cache/3.1/bundled/media-buy/sync-audiences-response.json +++ b/schemas/cache/3.1/bundled/media-buy/sync-audiences-response.json @@ -1104,7 +1104,7 @@ ], "properties": {}, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.957Z", + "generatedAt": "2026-06-30T19:14:40.300Z", "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/3.1/bundled/media-buy/sync-catalogs-request.json b/schemas/cache/3.1/bundled/media-buy/sync-catalogs-request.json index 0a9540f99..479bc4bd4 100644 --- a/schemas/cache/3.1/bundled/media-buy/sync-catalogs-request.json +++ b/schemas/cache/3.1/bundled/media-buy/sync-catalogs-request.json @@ -1372,7 +1372,7 @@ } ], "_bundled": { - "generatedAt": "2026-06-18T08:17:00.959Z", + "generatedAt": "2026-06-30T19:14:40.302Z", "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/3.1/bundled/media-buy/sync-catalogs-response.json b/schemas/cache/3.1/bundled/media-buy/sync-catalogs-response.json index a5d980003..6eb9182c0 100644 --- a/schemas/cache/3.1/bundled/media-buy/sync-catalogs-response.json +++ b/schemas/cache/3.1/bundled/media-buy/sync-catalogs-response.json @@ -1089,7 +1089,7 @@ ], "properties": {}, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.961Z", + "generatedAt": "2026-06-30T19:14:40.303Z", "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/3.1/bundled/media-buy/sync-event-sources-request.json b/schemas/cache/3.1/bundled/media-buy/sync-event-sources-request.json index 750106ae8..22e31f4f0 100644 --- a/schemas/cache/3.1/bundled/media-buy/sync-event-sources-request.json +++ b/schemas/cache/3.1/bundled/media-buy/sync-event-sources-request.json @@ -905,7 +905,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.962Z", + "generatedAt": "2026-06-30T19:14:40.304Z", "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/3.1/bundled/media-buy/sync-event-sources-response.json b/schemas/cache/3.1/bundled/media-buy/sync-event-sources-response.json index 5f3ae88d5..e0e303a66 100644 --- a/schemas/cache/3.1/bundled/media-buy/sync-event-sources-response.json +++ b/schemas/cache/3.1/bundled/media-buy/sync-event-sources-response.json @@ -1098,7 +1098,7 @@ ], "properties": {}, "_bundled": { - "generatedAt": "2026-06-18T08:17:00.963Z", + "generatedAt": "2026-06-30T19:14:40.306Z", "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/3.1/bundled/media-buy/update-media-buy-request.json b/schemas/cache/3.1/bundled/media-buy/update-media-buy-request.json index 33fe0eb61..704838f6d 100644 --- a/schemas/cache/3.1/bundled/media-buy/update-media-buy-request.json +++ b/schemas/cache/3.1/bundled/media-buy/update-media-buy-request.json @@ -5297,7 +5297,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -5313,12 +5314,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -6218,7 +6219,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -11204,7 +11205,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -11220,12 +11222,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -14146,7 +14148,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -14162,12 +14165,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -15067,7 +15070,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -20053,7 +20056,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -20069,12 +20073,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -29845,7 +29849,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -29861,12 +29866,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -30766,7 +30771,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -35752,7 +35757,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -35768,12 +35774,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -38694,7 +38700,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -38710,12 +38717,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -39615,7 +39622,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -44601,7 +44608,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -44617,12 +44625,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -48810,7 +48818,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.011Z", + "generatedAt": "2026-06-30T19:14:40.348Z", "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/3.1/bundled/media-buy/update-media-buy-response.json b/schemas/cache/3.1/bundled/media-buy/update-media-buy-response.json index d6c5e06f8..2f10abc97 100644 --- a/schemas/cache/3.1/bundled/media-buy/update-media-buy-response.json +++ b/schemas/cache/3.1/bundled/media-buy/update-media-buy-response.json @@ -8068,7 +8068,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.035Z", + "generatedAt": "2026-06-30T19:14:40.363Z", "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/3.1/bundled/property/create-property-list-request.json b/schemas/cache/3.1/bundled/property/create-property-list-request.json index 22eed9db0..6732e98a1 100644 --- a/schemas/cache/3.1/bundled/property/create-property-list-request.json +++ b/schemas/cache/3.1/bundled/property/create-property-list-request.json @@ -1602,7 +1602,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.039Z", + "generatedAt": "2026-06-30T19:14:40.366Z", "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/3.1/bundled/property/create-property-list-response.json b/schemas/cache/3.1/bundled/property/create-property-list-response.json index b8b39880e..61abf9097 100644 --- a/schemas/cache/3.1/bundled/property/create-property-list-response.json +++ b/schemas/cache/3.1/bundled/property/create-property-list-response.json @@ -2322,7 +2322,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.044Z", + "generatedAt": "2026-06-30T19:14:40.368Z", "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/3.1/bundled/property/delete-property-list-request.json b/schemas/cache/3.1/bundled/property/delete-property-list-request.json index e05f009a8..3e81e81dc 100644 --- a/schemas/cache/3.1/bundled/property/delete-property-list-request.json +++ b/schemas/cache/3.1/bundled/property/delete-property-list-request.json @@ -707,7 +707,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.045Z", + "generatedAt": "2026-06-30T19:14:40.369Z", "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/3.1/bundled/property/delete-property-list-response.json b/schemas/cache/3.1/bundled/property/delete-property-list-response.json index 17715570c..6a4c15c37 100644 --- a/schemas/cache/3.1/bundled/property/delete-property-list-response.json +++ b/schemas/cache/3.1/bundled/property/delete-property-list-response.json @@ -456,7 +456,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.046Z", + "generatedAt": "2026-06-30T19:14:40.370Z", "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/3.1/bundled/property/get-property-list-request.json b/schemas/cache/3.1/bundled/property/get-property-list-request.json index b78dbd090..eeedc66fe 100644 --- a/schemas/cache/3.1/bundled/property/get-property-list-request.json +++ b/schemas/cache/3.1/bundled/property/get-property-list-request.json @@ -721,7 +721,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.047Z", + "generatedAt": "2026-06-30T19:14:40.371Z", "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/3.1/bundled/property/get-property-list-response.json b/schemas/cache/3.1/bundled/property/get-property-list-response.json index 5dabd05d7..ce53e271f 100644 --- a/schemas/cache/3.1/bundled/property/get-property-list-response.json +++ b/schemas/cache/3.1/bundled/property/get-property-list-response.json @@ -2395,7 +2395,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.050Z", + "generatedAt": "2026-06-30T19:14:40.373Z", "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/3.1/bundled/property/list-property-lists-request.json b/schemas/cache/3.1/bundled/property/list-property-lists-request.json index 4d7aaa9aa..66d221dfb 100644 --- a/schemas/cache/3.1/bundled/property/list-property-lists-request.json +++ b/schemas/cache/3.1/bundled/property/list-property-lists-request.json @@ -713,7 +713,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.051Z", + "generatedAt": "2026-06-30T19:14:40.375Z", "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/3.1/bundled/property/list-property-lists-response.json b/schemas/cache/3.1/bundled/property/list-property-lists-response.json index 956873807..85be20091 100644 --- a/schemas/cache/3.1/bundled/property/list-property-lists-response.json +++ b/schemas/cache/3.1/bundled/property/list-property-lists-response.json @@ -2340,7 +2340,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.054Z", + "generatedAt": "2026-06-30T19:14:40.377Z", "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/3.1/bundled/property/update-property-list-request.json b/schemas/cache/3.1/bundled/property/update-property-list-request.json index bf79f559d..6ab91de0a 100644 --- a/schemas/cache/3.1/bundled/property/update-property-list-request.json +++ b/schemas/cache/3.1/bundled/property/update-property-list-request.json @@ -1611,7 +1611,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.056Z", + "generatedAt": "2026-06-30T19:14:40.379Z", "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/3.1/bundled/property/update-property-list-response.json b/schemas/cache/3.1/bundled/property/update-property-list-response.json index 6e659b5ac..91c332009 100644 --- a/schemas/cache/3.1/bundled/property/update-property-list-response.json +++ b/schemas/cache/3.1/bundled/property/update-property-list-response.json @@ -2317,7 +2317,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.059Z", + "generatedAt": "2026-06-30T19:14:40.381Z", "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/3.1/bundled/property/validate-property-delivery-request.json b/schemas/cache/3.1/bundled/property/validate-property-delivery-request.json index 6af37b860..c9b0b6db3 100644 --- a/schemas/cache/3.1/bundled/property/validate-property-delivery-request.json +++ b/schemas/cache/3.1/bundled/property/validate-property-delivery-request.json @@ -817,7 +817,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.061Z", + "generatedAt": "2026-06-30T19:14:40.382Z", "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/3.1/bundled/property/validate-property-delivery-response.json b/schemas/cache/3.1/bundled/property/validate-property-delivery-response.json index 3e8fc61e1..18cd71fd8 100644 --- a/schemas/cache/3.1/bundled/property/validate-property-delivery-response.json +++ b/schemas/cache/3.1/bundled/property/validate-property-delivery-response.json @@ -830,7 +830,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.062Z", + "generatedAt": "2026-06-30T19:14:40.384Z", "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/3.1/bundled/protocol/get-adcp-capabilities-request.json b/schemas/cache/3.1/bundled/protocol/get-adcp-capabilities-request.json index 6a01b7bc1..2705f8d2f 100644 --- a/schemas/cache/3.1/bundled/protocol/get-adcp-capabilities-request.json +++ b/schemas/cache/3.1/bundled/protocol/get-adcp-capabilities-request.json @@ -60,7 +60,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.062Z", + "generatedAt": "2026-06-30T19:14:40.384Z", "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/3.1/bundled/protocol/get-adcp-capabilities-response.json b/schemas/cache/3.1/bundled/protocol/get-adcp-capabilities-response.json index 00e6b534b..ce604d8f6 100644 --- a/schemas/cache/3.1/bundled/protocol/get-adcp-capabilities-response.json +++ b/schemas/cache/3.1/bundled/protocol/get-adcp-capabilities-response.json @@ -699,6 +699,11 @@ "description": "Conformance declaration that this seller supports the full proposal lifecycle on get_products: returned proposals are actionable, draft proposals can be finalized with buying_mode: 'refine' + action: 'finalize', and committed proposals can be executed via create_media_buy with proposal_id before expires_at. Buyers SHOULD NOT use this field to decide whether a specific returned proposal is executable; proposal_status is the per-proposal source of truth. A declaration of true opts the seller into proposal-lifecycle grading. When false or absent, conformance runners skip proposal-lifecycle storyboards, but buyers should still honor any proposals the seller actually returns.", "default": false }, + "governance_aware": { + "type": "boolean", + "description": "Conformance declaration that this seller consults a registered governance agent (via sync_governance plus an outbound check_governance call) before committing a media buy, and surfaces GOVERNANCE_DENIED when the governance agent denies. A declaration of true opts the seller into governance-denial grading (media_buy_seller/governance_denied, media_buy_seller/governance_denied_recovery). When false or absent, conformance runners skip those storyboards - a seller that does not implement outbound governance consultation is not expected to produce GOVERNANCE_DENIED. This is independent of baseline sync_governance registration, which remains gradeable on its own.", + "default": false + }, "propagation_surfaces": { "type": "array", "description": "Where this seller surfaces dependency-resource impairments (creative suspended/rejected post-approval, audience suspended, catalog item withdrawn, event source insufficient, property depublished) to buyers. Non-exclusive: a seller mirroring impairments on both the buy snapshot AND firing webhooks declares `[\"snapshot\", \"webhook\"]` (the common case for premium guaranteed sellers). Each value names one surface where buyers can observe an impairment:\n\n- **`snapshot`** \u2014 seller propagates resource transitions into `media_buy.health` and `media_buy.impairments[]` on the next `get_media_buys` read. The `impairment.coherence` compliance assertion grades this surface; storyboards that exercise it (`media_buy_seller/dependency_impairment`, `media_buy_seller/dependency_impairment_cardinality`) require `\"snapshot\"` to be declared, else they grade `not_applicable`.\n- **`webhook`** \u2014 seller fires `notification-type: impairment` webhooks (configured via `push_notification_config`). Sellers declaring `\"webhook\"` MUST satisfy the persistent-channel webhook contract for the impairment event type. A seller declaring `[\"webhook\"]` without `\"snapshot\"` is webhook-only \u2014 buyers reconcile state from the push channel alone, and snapshot-coherence storyboards grade `not_applicable`.\n- **`out_of_band`** \u2014 seller propagates via channels outside the AdCP protocol surface entirely (email to trafficker, separate dashboard, partner-specific notification feed). Long-tail and enterprise-bundled platforms commonly use this when impairment workflows are managed in human channels. Sellers declaring only `[\"out_of_band\"]` are not graded by snapshot or webhook compliance \u2014 their bar is the offline agreement, not a protocol assertion. If a seller has impairment data in their API under a non-AdCP field name (a mapping gap, not truly out-of-band), they SHOULD document the mapping rather than declare `out_of_band` \u2014 the spec's gap, not the seller's posture, is what `out_of_band` legitimately covers.\n\nDefault: `[\"snapshot\"]` when absent (preserves the existing snapshot-coherence contract for sellers that don't declare). Empty array `[]` is invalid (`minItems: 1`) \u2014 omit the field to inherit the default rather than declaring no surfaces. Pick the surfaces that honestly describe where buyers will see impairments on this agent. Mixing is normative \u2014 `[\"snapshot\", \"webhook\"]` is the documented common case; `[\"snapshot\", \"webhook\", \"out_of_band\"]` is valid for sellers that ship all three surfaces (rare but legal). See lifecycle.mdx \u00a7 Compliance for the per-surface contract.", @@ -11745,7 +11750,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.073Z", + "generatedAt": "2026-06-30T19:14:40.392Z", "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/3.1/bundled/protocol/get-task-status-request.json b/schemas/cache/3.1/bundled/protocol/get-task-status-request.json index ae73f1cb5..68e789f28 100644 --- a/schemas/cache/3.1/bundled/protocol/get-task-status-request.json +++ b/schemas/cache/3.1/bundled/protocol/get-task-status-request.json @@ -737,7 +737,7 @@ } ], "_bundled": { - "generatedAt": "2026-06-18T08:17:01.078Z", + "generatedAt": "2026-06-30T19:14:40.395Z", "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/3.1/bundled/protocol/get-task-status-response.json b/schemas/cache/3.1/bundled/protocol/get-task-status-response.json index d7d56e0e5..1dcc592c0 100644 --- a/schemas/cache/3.1/bundled/protocol/get-task-status-response.json +++ b/schemas/cache/3.1/bundled/protocol/get-task-status-response.json @@ -36164,7 +36164,7 @@ }, "pagination": { "title": "Pagination Response", - "description": "Standard cursor-based pagination metadata for list responses", + "description": "Cursor metadata for paginated get_products responses. In brief/refine mode, continuation pages bound returned products[] for the seller's curated or refined answer; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope, and pagination does not convert the response into an exhaustive feed contract. In wholesale mode, continuation pages walk the wholesale product feed.", "type": "object", "properties": { "has_more": { @@ -92604,7 +92604,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -92620,12 +92621,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -93525,7 +93526,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -98511,7 +98512,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -98527,12 +98529,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -101453,7 +101455,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -101469,12 +101472,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -102374,7 +102377,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -107360,7 +107363,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -107376,12 +107380,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -111946,7 +111950,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -111962,12 +111967,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -112867,7 +112872,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -117853,7 +117858,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -117869,12 +117875,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -120795,7 +120801,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -120811,12 +120818,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -121716,7 +121723,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -126702,7 +126709,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -126718,12 +126726,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -132169,7 +132177,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -132185,12 +132194,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -133090,7 +133099,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -138076,7 +138085,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -138092,12 +138102,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -141018,7 +141028,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -141034,12 +141045,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -141939,7 +141950,7 @@ }, { "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { @@ -146925,7 +146936,8 @@ }, { "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -146941,12 +146953,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", @@ -156018,7 +156030,7 @@ ], "enumDescriptions": { "guaranteed": "Reserved inventory with guaranteed delivery", - "non_guaranteed": "Auction-based inventory without delivery guarantees" + "non_guaranteed": "Inventory without reserved or guaranteed delivery, commonly auction-based or otherwise best-effort. Do not use for scheduled broadcast buys solely because final audience delivery is estimated from historical ranges or settles through third-party measurement." } }, "Exclusivity": { @@ -157995,7 +158007,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.243Z", + "generatedAt": "2026-06-30T19:14:40.809Z", "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/3.1/bundled/protocol/list-tasks-request.json b/schemas/cache/3.1/bundled/protocol/list-tasks-request.json index f5bdf5c8c..bfc976f0e 100644 --- a/schemas/cache/3.1/bundled/protocol/list-tasks-request.json +++ b/schemas/cache/3.1/bundled/protocol/list-tasks-request.json @@ -993,7 +993,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.305Z", + "generatedAt": "2026-06-30T19:14:40.842Z", "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/3.1/bundled/protocol/list-tasks-response.json b/schemas/cache/3.1/bundled/protocol/list-tasks-response.json index cdf91c79e..4971339b8 100644 --- a/schemas/cache/3.1/bundled/protocol/list-tasks-response.json +++ b/schemas/cache/3.1/bundled/protocol/list-tasks-response.json @@ -665,7 +665,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.306Z", + "generatedAt": "2026-06-30T19:14:40.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/3.1/bundled/signals/activate-signal-request.json b/schemas/cache/3.1/bundled/signals/activate-signal-request.json index 43845c7fa..e7ffc67ba 100644 --- a/schemas/cache/3.1/bundled/signals/activate-signal-request.json +++ b/schemas/cache/3.1/bundled/signals/activate-signal-request.json @@ -781,7 +781,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.307Z", + "generatedAt": "2026-06-30T19:14:40.844Z", "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/3.1/bundled/signals/activate-signal-response.json b/schemas/cache/3.1/bundled/signals/activate-signal-response.json index 8658bcb2f..d3d60fa35 100644 --- a/schemas/cache/3.1/bundled/signals/activate-signal-response.json +++ b/schemas/cache/3.1/bundled/signals/activate-signal-response.json @@ -816,7 +816,7 @@ ], "properties": {}, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.309Z", + "generatedAt": "2026-06-30T19:14:40.845Z", "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/3.1/bundled/signals/get-signals-request.json b/schemas/cache/3.1/bundled/signals/get-signals-request.json index 78eab6de9..f44cff5bb 100644 --- a/schemas/cache/3.1/bundled/signals/get-signals-request.json +++ b/schemas/cache/3.1/bundled/signals/get-signals-request.json @@ -1286,7 +1286,7 @@ }, "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.310Z", + "generatedAt": "2026-06-30T19:14:40.846Z", "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/3.1/bundled/signals/get-signals-response.json b/schemas/cache/3.1/bundled/signals/get-signals-response.json index 82a93cd7d..d98224a5d 100644 --- a/schemas/cache/3.1/bundled/signals/get-signals-response.json +++ b/schemas/cache/3.1/bundled/signals/get-signals-response.json @@ -5608,7 +5608,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.317Z", + "generatedAt": "2026-06-30T19:14:40.851Z", "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/3.1/bundled/sponsored-intelligence/si-get-offering-request.json b/schemas/cache/3.1/bundled/sponsored-intelligence/si-get-offering-request.json index e040de3a3..1aa19e1ce 100644 --- a/schemas/cache/3.1/bundled/sponsored-intelligence/si-get-offering-request.json +++ b/schemas/cache/3.1/bundled/sponsored-intelligence/si-get-offering-request.json @@ -70,7 +70,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.319Z", + "generatedAt": "2026-06-30T19:14:40.852Z", "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/3.1/bundled/sponsored-intelligence/si-get-offering-response.json b/schemas/cache/3.1/bundled/sponsored-intelligence/si-get-offering-response.json index c82aaae0e..3f0b7fb8a 100644 --- a/schemas/cache/3.1/bundled/sponsored-intelligence/si-get-offering-response.json +++ b/schemas/cache/3.1/bundled/sponsored-intelligence/si-get-offering-response.json @@ -1477,7 +1477,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.321Z", + "generatedAt": "2026-06-30T19:14:40.853Z", "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/3.1/bundled/sponsored-intelligence/si-initiate-session-request.json b/schemas/cache/3.1/bundled/sponsored-intelligence/si-initiate-session-request.json index cf567281d..d8e916297 100644 --- a/schemas/cache/3.1/bundled/sponsored-intelligence/si-initiate-session-request.json +++ b/schemas/cache/3.1/bundled/sponsored-intelligence/si-initiate-session-request.json @@ -1400,7 +1400,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.323Z", + "generatedAt": "2026-06-30T19:14:40.855Z", "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/3.1/bundled/sponsored-intelligence/si-initiate-session-response.json b/schemas/cache/3.1/bundled/sponsored-intelligence/si-initiate-session-response.json index e439efc19..a5595580a 100644 --- a/schemas/cache/3.1/bundled/sponsored-intelligence/si-initiate-session-response.json +++ b/schemas/cache/3.1/bundled/sponsored-intelligence/si-initiate-session-response.json @@ -1859,7 +1859,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.325Z", + "generatedAt": "2026-06-30T19:14:40.857Z", "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/3.1/bundled/sponsored-intelligence/si-send-message-request.json b/schemas/cache/3.1/bundled/sponsored-intelligence/si-send-message-request.json index e314c6bc1..13f3e9309 100644 --- a/schemas/cache/3.1/bundled/sponsored-intelligence/si-send-message-request.json +++ b/schemas/cache/3.1/bundled/sponsored-intelligence/si-send-message-request.json @@ -1159,7 +1159,7 @@ } }, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.327Z", + "generatedAt": "2026-06-30T19:14:40.858Z", "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/3.1/bundled/sponsored-intelligence/si-send-message-response.json b/schemas/cache/3.1/bundled/sponsored-intelligence/si-send-message-response.json index 58c630538..67ac14c82 100644 --- a/schemas/cache/3.1/bundled/sponsored-intelligence/si-send-message-response.json +++ b/schemas/cache/3.1/bundled/sponsored-intelligence/si-send-message-response.json @@ -1830,7 +1830,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.329Z", + "generatedAt": "2026-06-30T19:14:40.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/3.1/bundled/sponsored-intelligence/si-terminate-session-request.json b/schemas/cache/3.1/bundled/sponsored-intelligence/si-terminate-session-request.json index e8b06e936..2e2163f15 100644 --- a/schemas/cache/3.1/bundled/sponsored-intelligence/si-terminate-session-request.json +++ b/schemas/cache/3.1/bundled/sponsored-intelligence/si-terminate-session-request.json @@ -100,7 +100,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.330Z", + "generatedAt": "2026-06-30T19:14:40.860Z", "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/3.1/bundled/sponsored-intelligence/si-terminate-session-response.json b/schemas/cache/3.1/bundled/sponsored-intelligence/si-terminate-session-response.json index bf97c25c1..c41a5ddaf 100644 --- a/schemas/cache/3.1/bundled/sponsored-intelligence/si-terminate-session-response.json +++ b/schemas/cache/3.1/bundled/sponsored-intelligence/si-terminate-session-response.json @@ -642,7 +642,7 @@ ], "additionalProperties": true, "_bundled": { - "generatedAt": "2026-06-18T08:17:01.331Z", + "generatedAt": "2026-06-30T19:14:40.860Z", "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/3.1/core/assets/vast-asset.json b/schemas/cache/3.1/core/assets/vast-asset.json index e1565f288..8b7bfd987 100644 --- a/schemas/cache/3.1/core/assets/vast-asset.json +++ b/schemas/cache/3.1/core/assets/vast-asset.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "VAST Asset", - "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.", "type": "object", "properties": { "asset_type": { diff --git a/schemas/cache/3.1/core/assets/video-asset.json b/schemas/cache/3.1/core/assets/video-asset.json index 0204e5176..b094994c2 100644 --- a/schemas/cache/3.1/core/assets/video-asset.json +++ b/schemas/cache/3.1/core/assets/video-asset.json @@ -1,7 +1,8 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Video Asset", - "description": "Video asset with URL and technical specifications including audio track properties", + "description": "A hosted video file delivered directly (e.g., an MP4 you host), with URL and technical specifications including audio track properties. `width` and `height` are required because a hosted video file has intrinsic, native pixel dimensions that are known when the file is created. Tag-delivered video uses the separate `vast` asset, which carries no `width`/`height`: a VAST response resolves geometry per-`MediaFile` at serve time, so there is no single width/height for the ad. Aspect-ratio and size *constraints* (what a placement accepts) belong on the format/requirements layer, not on the asset.", + "$comment": "Dimension policy is deliberate and differs by asset type: a hosted `video` asset requires width/height (intrinsic pixels of a concrete file), while the `vast` asset omits them entirely (renditions are selected per-MediaFile by the player at serve time). Do not infer that AdCP forces a single width/height onto all video \u2014 only onto hosted files.", "type": "object", "properties": { "asset_type": { @@ -17,12 +18,12 @@ "width": { "type": "integer", "minimum": 1, - "description": "Width in pixels" + "description": "Width in pixels \u2014 the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)" }, "height": { "type": "integer", "minimum": 1, - "description": "Height in pixels" + "description": "Height in pixels \u2014 the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)" }, "duration_ms": { "type": "integer", diff --git a/schemas/cache/3.1/core/registry-feed-response.json b/schemas/cache/3.1/core/registry-feed-response.json index 1880e4fd7..444d7ac10 100644 --- a/schemas/cache/3.1/core/registry-feed-response.json +++ b/schemas/cache/3.1/core/registry-feed-response.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Registry Feed Response", - "description": "Response from GET /api/registry/feed. The events array contains cursor-ordered registry events; cursor is the value to pass on the next poll. See specs/registry-change-feed.md.", + "description": "Response from GET /api/registry/feed and the `feed` event body from GET /api/registry/feed/stream. The events array contains cursor-ordered registry events; cursor is the value to pass on the next poll or stream reconnect. See specs/registry-change-feed.md.", "type": "object", "properties": { "events": { @@ -21,12 +21,52 @@ "has_more": { "type": "boolean", "description": "True when more events are immediately available after cursor." + }, + "freshness": { + "type": "object", + "description": "Consumer-visible feed freshness metadata for the requested type filter.", + "properties": { + "generated_at": { + "type": "string", + "format": "date-time", + "description": "Server timestamp when this feed page was generated." + }, + "latest_event_created_at": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Newest event creation timestamp currently visible in the feed for the requested type filter. Null when no matching event exists inside retention." + }, + "lag_seconds": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "Seconds between generated_at and latest_event_created_at. Null when no matching event exists." + }, + "retention_days": { + "type": "integer", + "minimum": 1, + "description": "Number of days the registry retains feed cursors and events." + } + }, + "required": [ + "generated_at", + "latest_event_created_at", + "lag_seconds", + "retention_days" + ], + "additionalProperties": false } }, "required": [ "events", "cursor", - "has_more" + "has_more", + "freshness" ], "additionalProperties": true } \ No newline at end of file diff --git a/schemas/cache/3.1/core/x-entity-types.json b/schemas/cache/3.1/core/x-entity-types.json index 7c65af362..5f922da97 100644 --- a/schemas/cache/3.1/core/x-entity-types.json +++ b/schemas/cache/3.1/core/x-entity-types.json @@ -77,6 +77,6 @@ "si_session": "A sponsored-intelligence conversation session. `session_id` in sponsored-intelligence/* schemas.", "offering": "A brand-published offering (campaign, promotion, product set, service) promoted via traditional creatives or SI conversations. `offering_id` in core/offering.json, sponsored-intelligence/si-get-offering-*, and sponsored-intelligence/si-initiate-session-request. Also appears as a catalog item-type id when `core/catalog.json::type` is `offering`.", "vendor_metric": "A vendor-defined metric within a measurement vendor's vocabulary. `metric_id` in core/vendor-metric-id.json \u2014 used by reporting-capabilities.vendor_metrics declarations, delivery-metrics.vendor_metric_values emissions, and required_vendor_metrics filters. Identity is the tuple `(vendor.domain, vendor.brand_id, metric_id)` \u2014 the identifier is namespaced by the vendor's BrandRef, not globally unique. Vendor catalog (category, methodology, standard alignment) lives at the vendor's brand.json `agents[type='measurement']`.", - "identity_relying_party": "A verified-identity relying party an entity operates for attestation provenance in TMP Identity Match. `relying_party_id` in brand.json identity_relying_parties[] and tmp/identity-match-request.json attestation. Namespaced by the issuer (a vendor BrandRef, `core/brand-ref.json`) \u2014 identity is the tuple `(issuer.domain, issuer.brand_id, relying_party_id)`, mirroring vendor_metric's `(vendor.domain, vendor.brand_id, metric_id)`; the same string under a different issuer is a different relying party. The publishing owner (whose brand.json lists it) asserts ownership, and the receiver matches a forwarded attestation's `(issuer, relying_party_id)` against the claimed owner's published list; the issuer's own relying-party registry (e.g. World ID on-chain) is the authoritative root. One entity may operate many relying parties (scope=entity vs scope=property) \u2014 not 1:1 with an entity." + "identity_relying_party": "A verified-identity relying party an entity operates for attestation provenance in TMP Identity Match. `relying_party_id` in brand.json identity_relying_parties[] and trusted-match/identity-match-request.json attestation. Namespaced by the issuer (a vendor BrandRef, `core/brand-ref.json`) \u2014 identity is the tuple `(issuer.domain, issuer.brand_id, relying_party_id)`, mirroring vendor_metric's `(vendor.domain, vendor.brand_id, metric_id)`; the same string under a different issuer is a different relying party. The publishing owner (whose brand.json lists it) asserts ownership, and the receiver matches a forwarded attestation's `(issuer, relying_party_id)` against the claimed owner's published list; the issuer's own relying-party registry (e.g. World ID on-chain) is the authoritative root. One entity may operate many relying parties (scope=entity vs scope=property) \u2014 not 1:1 with an entity." } } \ No newline at end of file diff --git a/schemas/cache/3.1/creative/asset-types/index.json b/schemas/cache/3.1/creative/asset-types/index.json index 6671d7ba1..46d5e9b27 100644 --- a/schemas/cache/3.1/creative/asset-types/index.json +++ b/schemas/cache/3.1/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-06-18", + "lastUpdated": "2026-06-30", "asset_types": { "image": { "description": "Static image asset (JPG, PNG, GIF, WebP, SVG)", @@ -139,10 +139,37 @@ "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." }, - "published_version": "3.1.0", - "adcp_version": "3.1.0", - "baseUrl": "/schemas/3.1.0", + "published_version": "3.1.1", + "adcp_version": "3.1.1", + "baseUrl": "/schemas/3.1.1", + "protocol_layers": [ + { + "id": "negotiation", + "title": "Negotiation layer", + "description": "Planning-time protocols for discovery, buying, creative, signals, accounts, governance, brand identity, and sponsored intelligence.", + "schema_groups": [ + "media-buy", + "creative", + "signals", + "account", + "governance", + "brand", + "sponsored-intelligence" + ] + }, + { + "id": "decisioning-serving", + "title": "Decisioning and serving layer", + "description": "Trusted Match Protocol schemas for serve-time Context Match and Identity Match decisions.", + "schema_groups": [ + "trusted-match" + ] + } + ], + "stability": "stable", + "prerelease": false, + "deprecated": false, "versioning": { - "note": "AdCP uses build-time versioning. This directory contains schemas for AdCP 3.1.0. Full semantic versions are available at /schemas/{version}/ (e.g., /schemas/2.5.0/). Major version aliases point to the latest release: /schemas/v3/ \u2192 /schemas/3.1.0/." + "note": "AdCP uses build-time versioning. This directory contains schemas for AdCP 3.1.1. Full semantic versions are available at /schemas/{version}/ (e.g., /schemas/2.5.0/). Major version aliases point to the latest stable release in that major line; use /schemas/index.json or /schemas/latest.json for the canonical file-based pointer." } } \ No newline at end of file diff --git a/schemas/cache/3.1/enums/delivery-type.json b/schemas/cache/3.1/enums/delivery-type.json index 358190d90..0020090f2 100644 --- a/schemas/cache/3.1/enums/delivery-type.json +++ b/schemas/cache/3.1/enums/delivery-type.json @@ -9,6 +9,6 @@ ], "enumDescriptions": { "guaranteed": "Reserved inventory with guaranteed delivery", - "non_guaranteed": "Auction-based inventory without delivery guarantees" + "non_guaranteed": "Inventory without reserved or guaranteed delivery, commonly auction-based or otherwise best-effort. Do not use for scheduled broadcast buys solely because final audience delivery is estimated from historical ranges or settles through third-party measurement." } } \ No newline at end of file diff --git a/schemas/cache/3.1/extensions/index.json b/schemas/cache/3.1/extensions/index.json index bb594deab..a4b20617c 100644 --- a/schemas/cache/3.1/extensions/index.json +++ b/schemas/cache/3.1/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-06-18T08:16:59.734Z", + "_generatedAt": "2026-06-30T19:14:39.178Z", "extensions": {} } \ No newline at end of file diff --git a/schemas/cache/3.1/index.json b/schemas/cache/3.1/index.json index f128bb4d2..ebc66a61a 100644 --- a/schemas/cache/3.1/index.json +++ b/schemas/cache/3.1/index.json @@ -3,12 +3,39 @@ "title": "AdCP Schema Registry", "version": "1.0.0", "description": "Registry of all AdCP JSON schemas for validation and discovery", - "adcp_version": "3.1.0", + "adcp_version": "3.1.1", "versioning": { - "note": "AdCP uses build-time versioning. This directory contains schemas for AdCP 3.1.0. Full semantic versions are available at /schemas/{version}/ (e.g., /schemas/2.5.0/). Major version aliases point to the latest release: /schemas/v3/ \u2192 /schemas/3.1.0/." + "note": "AdCP uses build-time versioning. This directory contains schemas for AdCP 3.1.1. Full semantic versions are available at /schemas/{version}/ (e.g., /schemas/2.5.0/). Major version aliases point to the latest stable release in that major line; use /schemas/index.json or /schemas/latest.json for the canonical file-based pointer." }, - "lastUpdated": "2026-06-18", - "baseUrl": "/schemas/3.1.0", + "lastUpdated": "2026-06-30", + "baseUrl": "/schemas/3.1.1", + "stability": "stable", + "prerelease": false, + "deprecated": false, + "protocol_layers": [ + { + "id": "negotiation", + "title": "Negotiation layer", + "description": "Planning-time protocols for discovery, buying, creative, signals, accounts, governance, brand identity, and sponsored intelligence.", + "schema_groups": [ + "media-buy", + "creative", + "signals", + "account", + "governance", + "brand", + "sponsored-intelligence" + ] + }, + { + "id": "decisioning-serving", + "title": "Decisioning and serving layer", + "description": "Trusted Match Protocol schemas for serve-time Context Match and Identity Match decisions.", + "schema_groups": [ + "trusted-match" + ] + } + ], "schemas": { "core": { "description": "Core data models used throughout AdCP", @@ -1803,44 +1830,44 @@ "description": "Trusted Match Protocol (TMP) \u2014 real-time execution layer for activating pre-negotiated packages across any surface. Conformance invariants are normative in docs/trusted-match/specification.mdx; the cap-fire boundary contract is at docs/trusted-match/identity-match-implementation.mdx; a non-normative impression-tracker implementation reference (multi-identity dedup, fcap_keys labels, log-based data model, SDK primitives) is at docs/trusted-match/impression-tracker-implementation.mdx. Storage backend is an implementation choice; conformant services may use any store that satisfies the invariants.", "supporting-schemas": { "available-package": { - "$ref": "tmp/available-package.json", + "$ref": "trusted-match/available-package.json", "description": "A package available for contextual matching on a given impression opportunity" }, "offer": { - "$ref": "tmp/offer.json", + "$ref": "trusted-match/offer.json", "description": "Buyer's response to a context match \u2014 ranges from simple activation (package_id only) to rich offers with brand, price, summary, and creative manifest" }, "offer-price": { - "$ref": "tmp/offer-price.json", + "$ref": "trusted-match/offer-price.json", "description": "Lightweight price for variable-priced offers" }, "error": { - "$ref": "tmp/error.json", + "$ref": "trusted-match/error.json", "description": "Error response from a TMP provider or router when a request cannot be processed" }, "provider-registration": { - "$ref": "tmp/provider-registration.json", + "$ref": "trusted-match/provider-registration.json", "description": "TMP provider registration \u2014 endpoint, capabilities, and operational parameters for router configuration" } }, "operations": { "context-match": { "request": { - "$ref": "tmp/context-match-request.json", + "$ref": "trusted-match/context-match-request.json", "description": "Evaluate available packages against content context. Contains no user identity." }, "response": { - "$ref": "tmp/context-match-response.json", + "$ref": "trusted-match/context-match-response.json", "description": "Offers for matched packages with optional brand, price, summary, creative manifest, and targeting signals" } }, "identity-match": { "request": { - "$ref": "tmp/identity-match-request.json", + "$ref": "trusted-match/identity-match-request.json", "description": "Evaluate user eligibility for packages using an opaque identity token. Contains no page context." }, "response": { - "$ref": "tmp/identity-match-response.json", + "$ref": "trusted-match/identity-match-response.json", "description": "Per-package eligibility \u2014 boolean eligible plus optional intent score" } } @@ -1988,5 +2015,5 @@ "code": "// Use everit-org/json-schema or similar library" } ], - "published_version": "3.1.0" + "published_version": "3.1.1" } \ No newline at end of file diff --git a/schemas/cache/3.1/manifest.json b/schemas/cache/3.1/manifest.json index 7c14aae7d..405fbb246 100644 --- a/schemas/cache/3.1/manifest.json +++ b/schemas/cache/3.1/manifest.json @@ -1,7 +1,7 @@ { - "$schema": "/schemas/3.1.0/manifest.schema.json", - "adcp_version": "3.1.0", - "generated_at": "2026-06-18T08:16:59.912Z", + "$schema": "/schemas/3.1.1/manifest.schema.json", + "adcp_version": "3.1.1", + "generated_at": "2026-06-30T19:14:39.349Z", "tools": { "acquire_rights": { "protocol": "brand", diff --git a/schemas/cache/3.1/manifest.schema.json b/schemas/cache/3.1/manifest.schema.json index ec979f675..2343a4e3e 100644 --- a/schemas/cache/3.1/manifest.schema.json +++ b/schemas/cache/3.1/manifest.schema.json @@ -44,7 +44,7 @@ "properties": { "protocol": { "type": "string", - "description": "The protocol surface this tool belongs to. Derived from the source directory: media-buy, signals, governance, account, creative, brand, content-standards, property, collection, sponsored-intelligence, protocol, compliance, tmp.", + "description": "The protocol surface this tool belongs to. Derived from the source directory: media-buy, signals, governance, account, creative, brand, content-standards, property, collection, sponsored-intelligence, protocol, compliance, trusted-match.", "enum": [ "media-buy", "signals", @@ -58,7 +58,7 @@ "sponsored-intelligence", "protocol", "compliance", - "tmp", + "trusted-match", "a2ui" ] }, diff --git a/schemas/cache/3.1/media-buy/get-products-request.json b/schemas/cache/3.1/media-buy/get-products-request.json index ce71f2c2f..4e154c5c5 100644 --- a/schemas/cache/3.1/media-buy/get-products-request.json +++ b/schemas/cache/3.1/media-buy/get-products-request.json @@ -239,7 +239,8 @@ "description": "Optional webhook configuration for async terminal completion/failure notifications on curated discovery. Meaningful only for `buying_mode: \"brief\"` and `buying_mode: \"refine\"` requests that enter the async lifecycle. Submitted envelopes with `task_id` remain pollable through `get_task_status` (legacy `tasks/get`) whether or not this field is present. If a brief/refine request includes this field and the seller returns a Submitted envelope, the seller MUST deliver at least the terminal completion/failure notification to the configured URL; intermediate progress notifications are MAY. If the seller cannot honor the webhook channel, it MUST reject the request with a structured error instead of silently accepting. This field does not change wholesale timing semantics: sellers MUST NOT route `buying_mode: \"wholesale\"` requests through the async/Submitted arm or emit async delivery solely because `push_notification_config` is present; partial wholesale completion is reported via `incomplete[]`." }, "pagination": { - "$ref": "../core/pagination-request.json" + "$ref": "../core/pagination-request.json", + "description": "Cursor-based pagination controls for get_products. Valid in all buying modes. In brief mode, pagination bounds the seller's returned products[] for the curated answer to the brief and is not an exhaustive catalog-enumeration contract. In refine mode, pagination bounds the refined products[] result implied by refine[] and filters; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope. In wholesale mode, pagination walks the wholesale product feed and may be combined with wholesale feed versioning." }, "if_wholesale_feed_version": { "type": "string", diff --git a/schemas/cache/3.1/media-buy/get-products-response.json b/schemas/cache/3.1/media-buy/get-products-response.json index 9b015b752..3161fad02 100644 --- a/schemas/cache/3.1/media-buy/get-products-response.json +++ b/schemas/cache/3.1/media-buy/get-products-response.json @@ -298,7 +298,8 @@ ] }, "pagination": { - "$ref": "../core/pagination-response.json" + "$ref": "../core/pagination-response.json", + "description": "Cursor metadata for paginated get_products responses. In brief/refine mode, continuation pages bound returned products[] for the seller's curated or refined answer; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope, and pagination does not convert the response into an exhaustive feed contract. In wholesale mode, continuation pages walk the wholesale product feed." }, "wholesale_feed_version": { "type": "string", diff --git a/schemas/cache/3.1/protocol/get-adcp-capabilities-response.json b/schemas/cache/3.1/protocol/get-adcp-capabilities-response.json index 3bdcaa7f9..9d30adca8 100644 --- a/schemas/cache/3.1/protocol/get-adcp-capabilities-response.json +++ b/schemas/cache/3.1/protocol/get-adcp-capabilities-response.json @@ -245,6 +245,11 @@ "description": "Conformance declaration that this seller supports the full proposal lifecycle on get_products: returned proposals are actionable, draft proposals can be finalized with buying_mode: 'refine' + action: 'finalize', and committed proposals can be executed via create_media_buy with proposal_id before expires_at. Buyers SHOULD NOT use this field to decide whether a specific returned proposal is executable; proposal_status is the per-proposal source of truth. A declaration of true opts the seller into proposal-lifecycle grading. When false or absent, conformance runners skip proposal-lifecycle storyboards, but buyers should still honor any proposals the seller actually returns.", "default": false }, + "governance_aware": { + "type": "boolean", + "description": "Conformance declaration that this seller consults a registered governance agent (via sync_governance plus an outbound check_governance call) before committing a media buy, and surfaces GOVERNANCE_DENIED when the governance agent denies. A declaration of true opts the seller into governance-denial grading (media_buy_seller/governance_denied, media_buy_seller/governance_denied_recovery). When false or absent, conformance runners skip those storyboards - a seller that does not implement outbound governance consultation is not expected to produce GOVERNANCE_DENIED. This is independent of baseline sync_governance registration, which remains gradeable on its own.", + "default": false + }, "propagation_surfaces": { "type": "array", "description": "Where this seller surfaces dependency-resource impairments (creative suspended/rejected post-approval, audience suspended, catalog item withdrawn, event source insufficient, property depublished) to buyers. Non-exclusive: a seller mirroring impairments on both the buy snapshot AND firing webhooks declares `[\"snapshot\", \"webhook\"]` (the common case for premium guaranteed sellers). Each value names one surface where buyers can observe an impairment:\n\n- **`snapshot`** \u2014 seller propagates resource transitions into `media_buy.health` and `media_buy.impairments[]` on the next `get_media_buys` read. The `impairment.coherence` compliance assertion grades this surface; storyboards that exercise it (`media_buy_seller/dependency_impairment`, `media_buy_seller/dependency_impairment_cardinality`) require `\"snapshot\"` to be declared, else they grade `not_applicable`.\n- **`webhook`** \u2014 seller fires `notification-type: impairment` webhooks (configured via `push_notification_config`). Sellers declaring `\"webhook\"` MUST satisfy the persistent-channel webhook contract for the impairment event type. A seller declaring `[\"webhook\"]` without `\"snapshot\"` is webhook-only \u2014 buyers reconcile state from the push channel alone, and snapshot-coherence storyboards grade `not_applicable`.\n- **`out_of_band`** \u2014 seller propagates via channels outside the AdCP protocol surface entirely (email to trafficker, separate dashboard, partner-specific notification feed). Long-tail and enterprise-bundled platforms commonly use this when impairment workflows are managed in human channels. Sellers declaring only `[\"out_of_band\"]` are not graded by snapshot or webhook compliance \u2014 their bar is the offline agreement, not a protocol assertion. If a seller has impairment data in their API under a non-AdCP field name (a mapping gap, not truly out-of-band), they SHOULD document the mapping rather than declare `out_of_band` \u2014 the spec's gap, not the seller's posture, is what `out_of_band` legitimately covers.\n\nDefault: `[\"snapshot\"]` when absent (preserves the existing snapshot-coherence contract for sellers that don't declare). Empty array `[]` is invalid (`minItems: 1`) \u2014 omit the field to inherit the default rather than declaring no surfaces. Pick the surfaces that honestly describe where buyers will see impairments on this agent. Mixing is normative \u2014 `[\"snapshot\", \"webhook\"]` is the documented common case; `[\"snapshot\", \"webhook\", \"out_of_band\"]` is valid for sellers that ship all three surfaces (rare but legal). See lifecycle.mdx \u00a7 Compliance for the per-surface contract.", diff --git a/schemas/cache/3.1/tmp/identity-match-response.json b/schemas/cache/3.1/tmp/identity-match-response.json deleted file mode 100644 index a140c2a78..000000000 --- a/schemas/cache/3.1/tmp/identity-match-response.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Identity Match Response", - "description": "Response indicating which packages the user is eligible for. The serve_window_sec field defines a per-package single-shot fcap: after serving the user one impression on each eligible package, the publisher MUST re-query Identity Match before serving from those packages again. Extension fields (ext, context) are intentionally omitted to prevent data leakage across the identity privacy boundary.", - "type": "object", - "allOf": [ - { - "$ref": "../core/version-envelope.json" - }, - { - "$ref": "../core/protocol-envelope.json" - } - ], - "x-status": "experimental", - "properties": { - "type": { - "type": "string", - "const": "identity_match_response", - "description": "Message type discriminator for deserialization." - }, - "request_id": { - "type": "string", - "description": "Echoed request identifier from the identity match request" - }, - "eligible_package_ids": { - "type": "array", - "description": "Package IDs the user is eligible for. Packages not listed are ineligible.", - "items": { - "type": "string" - } - }, - "serve_window_sec": { - "type": "integer", - "description": "Per-package single-shot fcap window, in seconds. After serving the user one impression on each eligible package within this window, the publisher MUST re-query Identity Match before serving from those packages again. This is NOT a router response cache TTL \u2014 it is a buyer-asserted serve throttle. Multi-impression frequency caps are handled separately by the buyer's impression tracker, which writes cap-fire events to the IdentityMatch cap-state store at the boundary regardless of this window. Maximum 300 \u2014 longer windows reduce IdentityMatch load but coarsen fcap granularity below what most campaigns require.", - "minimum": 1, - "maximum": 300 - }, - "tmpx": { - "type": "string", - "description": "HPKE-encrypted exposure token containing the resolved user identity tokens. The publisher substitutes this into creative tracking URLs as {TMPX}. The buyer's impression pixel receives the token at serve time, enabling real-time per-user frequency state updates. Wire format: kid.base64url_nopad(ciphertext) \u2014 unpadded base64url per RFC 4648 section 5 (no = characters). Publishers MUST treat this value as opaque pass-through data." - } - }, - "required": [ - "type", - "request_id", - "eligible_package_ids", - "serve_window_sec" - ], - "additionalProperties": true -} \ No newline at end of file diff --git a/schemas/cache/3.1/tmp/available-package.json b/schemas/cache/3.1/trusted-match/available-package.json similarity index 100% rename from schemas/cache/3.1/tmp/available-package.json rename to schemas/cache/3.1/trusted-match/available-package.json diff --git a/schemas/cache/3.1/tmp/context-match-request.json b/schemas/cache/3.1/trusted-match/context-match-request.json similarity index 100% rename from schemas/cache/3.1/tmp/context-match-request.json rename to schemas/cache/3.1/trusted-match/context-match-request.json diff --git a/schemas/cache/3.1/tmp/context-match-response.json b/schemas/cache/3.1/trusted-match/context-match-response.json similarity index 100% rename from schemas/cache/3.1/tmp/context-match-response.json rename to schemas/cache/3.1/trusted-match/context-match-response.json diff --git a/schemas/cache/3.1/tmp/error.json b/schemas/cache/3.1/trusted-match/error.json similarity index 100% rename from schemas/cache/3.1/tmp/error.json rename to schemas/cache/3.1/trusted-match/error.json diff --git a/schemas/cache/3.1/tmp/identity-match-request.json b/schemas/cache/3.1/trusted-match/identity-match-request.json similarity index 100% rename from schemas/cache/3.1/tmp/identity-match-request.json rename to schemas/cache/3.1/trusted-match/identity-match-request.json diff --git a/schemas/cache/3.1/trusted-match/identity-match-response.json b/schemas/cache/3.1/trusted-match/identity-match-response.json new file mode 100644 index 000000000..12333515c --- /dev/null +++ b/schemas/cache/3.1/trusted-match/identity-match-response.json @@ -0,0 +1,107 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Identity Match Response", + "description": "Response indicating which packages the user is eligible for. The serve_window_sec field defines a per-package single-shot fcap: after serving the user one impression on each eligible package, the publisher MUST re-query Identity Match before serving from those packages again. Extension fields (ext, context) are intentionally omitted to prevent data leakage across the identity privacy boundary.", + "type": "object", + "allOf": [ + { + "$ref": "../core/version-envelope.json" + }, + { + "$ref": "../core/protocol-envelope.json" + } + ], + "x-status": "experimental", + "properties": { + "type": { + "type": "string", + "const": "identity_match_response", + "description": "Message type discriminator for deserialization." + }, + "request_id": { + "type": "string", + "description": "Echoed request identifier from the identity match request" + }, + "eligible_package_ids": { + "type": "array", + "description": "Package IDs the user is eligible for. Packages not listed are ineligible.", + "items": { + "type": "string" + } + }, + "serve_window_sec": { + "type": "integer", + "description": "Per-package single-shot fcap window, in seconds. After serving the user one impression on each eligible package within this window, the publisher MUST re-query Identity Match before serving from those packages again. This is NOT a router response cache TTL \u2014 it is a buyer-asserted serve throttle. Multi-impression frequency caps are handled separately by the buyer's impression tracker, which writes cap-fire events to the IdentityMatch cap-state store at the boundary regardless of this window. Maximum 300 \u2014 longer windows reduce IdentityMatch load but coarsen fcap granularity below what most campaigns require.", + "minimum": 1, + "maximum": 300 + }, + "tmpx": { + "type": "string", + "description": "DEPRECATED in favor of tmpx_providers. Routers MAY continue to populate this field for back-compat with consumers that only know the single-token shape; when both fields are present, tmpx_providers is authoritative. Single HPKE-encrypted exposure token containing the resolved user identity tokens. Wire format: kid.base64url_nopad(ciphertext) \u2014 unpadded base64url per RFC 4648 section 5 (no = characters). Publishers MUST treat this value as opaque pass-through data. Removed in 4.0." + }, + "tmpx_macros": { + "type": "array", + "description": "Provider-emitted: the identity agent's ordered TMPX chunks paired with the macro name each chunk fills. Macro names MUST be drawn from the provider's registered `tmpx_macros` list (provider-registration.json) and appear in the same order \u2014 names are part of operational setup, not protocol-synthesized. Capped at 2 chunks in v1; the cap MAY rise without a shape change. Each `value` is an opaque URL-safe wire string the publisher substitutes verbatim into the matching ad-server macro slot \u2014 publishers MUST NOT parse, decode, transform, or choose an encoding. The router collects entries from every provider that emits them into `tmpx_providers`, keyed by provider_id; consumers reading the merged response SHOULD consume `tmpx_providers` and ignore `tmpx_macros` at the root.", + "items": { + "$ref": "#/$defs/TmpxMacro" + }, + "minItems": 1, + "maxItems": 2 + }, + "tmpx_providers": { + "type": "object", + "description": "Router-populated: TMPX macro/value pairs grouped by the originating identity provider's provider_id, so the publisher fires each provider's tokens through that provider's specific ad-server macros (configured per provider in GAM / VAST URL / DOOH play log). Each entry's `macros[]` is a copy of the provider's emitted `tmpx_macros` ordered list. SHAPE CHANGE: was `Map` in the experimental surface that shipped in #5689; now `Map` to carry exact macro/value pairs and support multi-chunk TMPX. Sanctioned by the experimental contract (`x-status: experimental` on this schema). Required by router conformance when any identity provider emitted TMPX in this request; collapsing per-provider tokens into a single string loses attribution and breaks per-provider impression accounting. Map keys MUST be valid provider_ids registered for this fan-out. Publishers MUST traffic only the macro names the response advertises; macro names MUST NOT be derived from provider_id at runtime.", + "additionalProperties": { + "type": "object", + "properties": { + "macros": { + "type": "array", + "description": "Ordered TMPX macro/value pairs for this provider. Names MUST match the provider's registered `tmpx_macros`.", + "items": { + "$ref": "#/$defs/TmpxMacro" + }, + "minItems": 1, + "maxItems": 2 + } + }, + "required": [ + "macros" + ], + "additionalProperties": false + } + } + }, + "$defs": { + "TmpxMacro": { + "type": "object", + "description": "A single ad-server macro slot and the URL-safe value the publisher substitutes into it.", + "properties": { + "name": { + "type": "string", + "pattern": "^[A-Z][A-Z0-9_]*$", + "minLength": 1, + "maxLength": 64, + "description": "Macro name as configured in the publisher's ad server (e.g. `PIN_TMPX_1`). MUST appear in the emitting provider's registered `tmpx_macros` list. Provider-namespaced so the publisher can target distinct slots per provider." + }, + "value": { + "type": "string", + "minLength": 1, + "maxLength": 1024, + "description": "Opaque, URL-safe wire string the publisher substitutes verbatim into the named macro slot. Publishers MUST NOT parse, decode, or transform this value. The protocol fixes the wire format so platforms interoperate; a platform that can carry raw bytes MAY optimize privately but the wire contract remains the URL-safe string." + } + }, + "required": [ + "name", + "value" + ], + "additionalProperties": false + } + }, + "required": [ + "type", + "request_id", + "eligible_package_ids", + "serve_window_sec" + ], + "additionalProperties": true +} \ No newline at end of file diff --git a/schemas/cache/3.1/tmp/offer-price.json b/schemas/cache/3.1/trusted-match/offer-price.json similarity index 100% rename from schemas/cache/3.1/tmp/offer-price.json rename to schemas/cache/3.1/trusted-match/offer-price.json diff --git a/schemas/cache/3.1/tmp/offer.json b/schemas/cache/3.1/trusted-match/offer.json similarity index 100% rename from schemas/cache/3.1/tmp/offer.json rename to schemas/cache/3.1/trusted-match/offer.json diff --git a/schemas/cache/3.1/tmp/provider-registration.json b/schemas/cache/3.1/trusted-match/provider-registration.json similarity index 71% rename from schemas/cache/3.1/tmp/provider-registration.json rename to schemas/cache/3.1/trusted-match/provider-registration.json index 4ee83fd1d..1f769353e 100644 --- a/schemas/cache/3.1/tmp/provider-registration.json +++ b/schemas/cache/3.1/trusted-match/provider-registration.json @@ -7,7 +7,10 @@ "properties": { "provider_id": { "type": "string", - "description": "Stable identifier for this provider registration. Used in logs, metrics, and cache keys. Publishers assign this \u2014 it is not the provider's agent_url." + "description": "Stable identifier for this provider registration. Used in logs, metrics, cache keys, and as the key in `tmpx_providers` on the identity-match response so the publisher can route each provider's TMPX `macros[]` to that provider's pre-configured ad-server slots (names registered in `tmpx_macros` below \u2014 macro names MUST NOT be derived from `provider_id` at runtime). Publishers assign this \u2014 it is not the provider's agent_url. Charset is constrained to a safe alphanumeric/underscore set so the value can appear in operational surfaces (logs, metrics, dashboards) without quoting.", + "pattern": "^[A-Za-z0-9_]+$", + "minLength": 1, + "maxLength": 64 }, "endpoint": { "type": "string", @@ -61,6 +64,18 @@ "minimum": 0, "default": 0 }, + "tmpx_macros": { + "type": "array", + "description": "Stable, provider-namespaced ad-server macro names this provider's TMPX response fills, ordered. Publishers traffic these exact names in their ad server (GAM key-values, VAST URL macros, DOOH play-log fields); the router places each provider's TMPX chunks into the matching slots on the identity-match response (`tmpx_providers[provider_id].macros[]`). Names MUST be provider-namespaced so publishers can configure distinct macros per provider (e.g. `PIN_TMPX_1`, `PIN_TMPX_2` for one provider; `NOVA_TMPX_1` for another). Ordered so multi-chunk TMPX values (when the opaque token exceeds one macro slot) are placed deterministically. Capped at 2 entries in v1; the cap MAY be raised in a later version without a shape change. A provider that emits TMPX on its identity-match response (populates `tmpx_macros[]` there) MUST also register this list \u2014 otherwise the router has no slot names to forward \u2014 but the schema cannot enforce this because \"emits TMPX\" is not a schema-visible predicate. Providers that do not emit TMPX omit this field.", + "items": { + "type": "string", + "pattern": "^[A-Z][A-Z0-9_]*$", + "minLength": 1, + "maxLength": 64 + }, + "minItems": 1, + "maxItems": 2 + }, "status": { "type": "string", "description": "Provider lifecycle status. Active providers receive requests. Inactive providers are skipped entirely. Draining providers stop receiving new requests but in-flight requests complete normally.", diff --git a/scripts/consolidate_exports.py b/scripts/consolidate_exports.py index c7fd1ad24..c54d613dd 100644 --- a/scripts/consolidate_exports.py +++ b/scripts/consolidate_exports.py @@ -97,6 +97,11 @@ # with different Role enums. Export both qualified variants and expose # semantic aliases from aliases.py. "DeclaredBy": {"provenance", "si_sponsored_context"}, + # Trusted Match uses TmpxMacro for two different wire shapes: + # provider_registration defines the registered macro name as a string + # RootModel, while identity_match_response defines emitted macro/value + # pairs. Export both and expose semantic aliases from aliases.py. + "TmpxMacro": {"identity_match_response", "provider_registration"}, } diff --git a/scripts/post_generate_fixes.py b/scripts/post_generate_fixes.py index 9eb94e938..9b6d6523d 100644 --- a/scripts/post_generate_fixes.py +++ b/scripts/post_generate_fixes.py @@ -1847,6 +1847,120 @@ def fix_protocol_envelope_status_default() -> None: print(" core/protocol_envelope.py: defaulted status to completed") +def fix_trusted_match_runtime_validators() -> None: + """Restore Trusted Match constraints that datamodel-codegen does not model. + + JSON Schema conditionals and map-key descriptions are either flattened or + not represented in the generated Pydantic models. Keep the generated types + aligned with the schema's normative field descriptions. + """ + + provider_registration = OUTPUT_DIR / "trusted_match" / "provider_registration.py" + if provider_registration.exists(): + source = provider_registration.read_text() + if "_require_https_endpoint" in source: + print(" trusted_match/provider_registration.py validators already fixed") + else: + if "from pydantic import AnyUrl, ConfigDict, Field, RootModel" in source: + source = source.replace( + "from pydantic import AnyUrl, ConfigDict, Field, RootModel", + "from pydantic import AnyUrl, ConfigDict, Field, RootModel, field_validator, model_validator", + 1, + ) + else: + print(" trusted_match/provider_registration.py pydantic import shape not found") + source = "" + + if source: + validators_1 = """ + + @field_validator('endpoint') + @classmethod + def _require_https_endpoint(cls, value: AnyUrl) -> AnyUrl: + if value.scheme != 'https': + raise ValueError('endpoint must use https') + return value + + @model_validator(mode='after') + def _require_identity_match_dimensions(self) -> TmpProviderRegistration1: + if self.identity_match is True: + if not self.countries: + raise ValueError('countries is required when identity_match is true') + if not self.uid_types: + raise ValueError('uid_types is required when identity_match is true') + return self +""" + validators_2 = validators_1.replace( + "TmpProviderRegistration1", "TmpProviderRegistration2" + ) + source = source.replace( + "\n\nclass TmpProviderRegistration2(AdCPBaseModel):", + validators_1 + "\n\nclass TmpProviderRegistration2(AdCPBaseModel):", + 1, + ) + source = source.replace( + "\n\nclass TmpProviderRegistration(RootModel[TmpProviderRegistration1 | TmpProviderRegistration2]):", + validators_2 + + "\n\nclass TmpProviderRegistration(RootModel[TmpProviderRegistration1 | TmpProviderRegistration2]):", + 1, + ) + provider_registration.write_text(source) + print(" trusted_match/provider_registration.py: added runtime validators") + else: + print(" trusted_match/provider_registration.py not found (skipping)") + + identity_match_response = OUTPUT_DIR / "trusted_match" / "identity_match_response.py" + if not identity_match_response.exists(): + print(" trusted_match/identity_match_response.py not found (skipping)") + return + + source = identity_match_response.read_text() + if "_validate_tmpx_provider_ids" in source: + print(" trusted_match/identity_match_response.py validators already fixed") + return + + source = source.replace( + "from __future__ import annotations\n\n", + "from __future__ import annotations\n\nimport re\n\n", + 1, + ) + if "from pydantic import ConfigDict, Field" in source: + source = source.replace( + "from pydantic import ConfigDict, Field", + "from pydantic import ConfigDict, Field, model_validator", + 1, + ) + else: + print(" trusted_match/identity_match_response.py pydantic import shape not found") + return + + source = source.replace( + "from ..core.version_envelope import AdcpVersionEnvelope\n\n\n", + "from ..core.version_envelope import AdcpVersionEnvelope\n\n\n_PROVIDER_ID_PATTERN = re.compile(r'^[A-Za-z0-9_]{1,64}$')\n\n\n", + 1, + ) + source = ( + source.rstrip() + + """ + + @model_validator(mode='after') + def _validate_tmpx_provider_ids(self) -> IdentityMatchResponse: + if self.tmpx_providers is None: + return self + invalid = [ + provider_id + for provider_id in self.tmpx_providers + if not _PROVIDER_ID_PATTERN.fullmatch(provider_id) + ] + if invalid: + raise ValueError('tmpx_providers keys must be valid provider_id values') + return self +""" + ) + identity_match_response.write_text(source.rstrip() + "\n") + print(" trusted_match/identity_match_response.py: added runtime validators") + + def fix_wholesale_cache_scope_defaults() -> None: """Default beta 3 wholesale cache scope to public in typed responses.""" targets = [ @@ -3505,6 +3619,7 @@ def main(): fix_canceled_literal_defaults, fix_unchanged_literal_defaults, fix_protocol_envelope_status_default, + fix_trusted_match_runtime_validators, fix_wholesale_cache_scope_defaults, fix_product_publisher_property_model_coercion, fix_mcp_webhook_operation_id_optional, diff --git a/src/adcp/ADCP_VERSION b/src/adcp/ADCP_VERSION index fd2a01863..94ff29cc4 100644 --- a/src/adcp/ADCP_VERSION +++ b/src/adcp/ADCP_VERSION @@ -1 +1 @@ -3.1.0 +3.1.1 diff --git a/src/adcp/__init__.py b/src/adcp/__init__.py index ea46db41a..826ecc5e3 100644 --- a/src/adcp/__init__.py +++ b/src/adcp/__init__.py @@ -289,6 +289,7 @@ def _resolve_version() -> str: "Gtin", "IdentityMatchRequest", "IdentityMatchResponse", + "IdentityMatchTmpxMacro", "KellerType", "ListAccountsRequest", "ListAccountsResponse", @@ -329,6 +330,7 @@ def _resolve_version() -> str: "PriceGuidance", "PricingCurrency", "PricingModel", + "ProviderRegistrationTmpxMacro", "Product", "ProductFilters", "ProductSignalTargetingOption", @@ -842,6 +844,7 @@ def get_adcp_version() -> str: "ContextMatchResponse", "IdentityMatchRequest", "IdentityMatchResponse", + "IdentityMatchTmpxMacro", # Brand Rights "AcquireRightsRequest", "AcquireRightsResponse", @@ -1025,6 +1028,7 @@ def get_adcp_version() -> str: "MediaBuyStatus", "PricingModel", "PricingCurrency", + "ProviderRegistrationTmpxMacro", # Pricing-related types "CpaPricingOption", "CpcPricingOption", @@ -1483,6 +1487,7 @@ def get_adcp_version() -> str: Gtin, IdentityMatchRequest, IdentityMatchResponse, + IdentityMatchTmpxMacro, KellerType, # Account Operations ListAccountsRequest, @@ -1536,6 +1541,7 @@ def get_adcp_version() -> str: Proposal, ProvidePerformanceFeedbackRequest, ProvidePerformanceFeedbackResponse, + ProviderRegistrationTmpxMacro, PushNotificationConfig, Refine, ReportPlanOutcomeRequest, diff --git a/src/adcp/client.py b/src/adcp/client.py index 749989d91..47b6cf75a 100644 --- a/src/adcp/client.py +++ b/src/adcp/client.py @@ -300,10 +300,10 @@ from adcp.types.generated_poc.sponsored_intelligence.si_terminate_session_response import ( SiTerminateSessionResponse, ) -from adcp.types.generated_poc.tmp.context_match_request import ContextMatchRequest -from adcp.types.generated_poc.tmp.context_match_response import ContextMatchResponse -from adcp.types.generated_poc.tmp.identity_match_request import IdentityMatchRequest -from adcp.types.generated_poc.tmp.identity_match_response import IdentityMatchResponse +from adcp.types.generated_poc.trusted_match.context_match_request import ContextMatchRequest +from adcp.types.generated_poc.trusted_match.context_match_response import ContextMatchResponse +from adcp.types.generated_poc.trusted_match.identity_match_request import IdentityMatchRequest +from adcp.types.generated_poc.trusted_match.identity_match_response import IdentityMatchResponse from adcp.utils.operation_id import create_operation_id from adcp.validation.client_hooks import ValidationHookConfig from adcp.validation.version import resolve_bundle_key diff --git a/src/adcp/types/__init__.py b/src/adcp/types/__init__.py index d642b8c39..020133754 100644 --- a/src/adcp/types/__init__.py +++ b/src/adcp/types/__init__.py @@ -806,6 +806,9 @@ # DeclaredBy "ProvenanceDeclaredBy", "SiSponsoredContextDeclaredBy", + # TmpxMacro + "IdentityMatchTmpxMacro", + "ProviderRegistrationTmpxMacro", # Unit "DurationUnit", "OverlayUnit", @@ -1292,6 +1295,7 @@ def __dir__() -> list[str]: Identifier, IdentityMatchRequest, IdentityMatchResponse, + IdentityMatchTmpxMacro, ImageContent, ImageFormatAsset, ImageFormatGroupAsset, @@ -1441,6 +1445,7 @@ def __dir__() -> list[str]: ProvidePerformanceFeedbackResponse, ProvidePerformanceFeedbackResponse1, ProvidePerformanceFeedbackSuccessResponse, + ProviderRegistrationTmpxMacro, PublisherDomain, PublisherIdentifierTypes, PublisherProperties, diff --git a/src/adcp/types/_eager.py b/src/adcp/types/_eager.py index 6152e6bbb..c14601395 100644 --- a/src/adcp/types/_eager.py +++ b/src/adcp/types/_eager.py @@ -586,6 +586,7 @@ HtmlFormatAsset, HtmlFormatGroupAsset, HtmlPreviewRender, + IdentityMatchTmpxMacro, ImageFormatAsset, ImageFormatGroupAsset, InlineDaastAsset, @@ -627,6 +628,7 @@ ProvidePerformanceFeedbackErrorResponse, ProvidePerformanceFeedbackResponse1, ProvidePerformanceFeedbackSuccessResponse, + ProviderRegistrationTmpxMacro, PublisherProperties, PublisherPropertiesAll, PublisherPropertiesById, @@ -1202,6 +1204,7 @@ def __init__(self, *args: object, **kwargs: object) -> None: "Identifier", "IdentityMatchRequest", "IdentityMatchResponse", + "IdentityMatchTmpxMacro", "ImageContent", "ImageFormatAsset", "ImageFormatGroupAsset", @@ -1330,6 +1333,7 @@ def __init__(self, *args: object, **kwargs: object) -> None: "ProductFormatDeclaration", "ProductFormatSellerPreference", "ProductSignalTargetingOption", + "ProviderRegistrationTmpxMacro", "Property", "PropertyId", "PropertyIdActivationKey", diff --git a/src/adcp/types/_generated.py b/src/adcp/types/_generated.py index ba94c409f..8d1ad8d87 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-06-18 11:33:58 UTC +Generation date: 2026-07-01 04:37:49 UTC """ # ruff: noqa: E501, I001 @@ -1146,7 +1146,7 @@ StringArray, Tracks, ) -from adcp.types.generated_poc.core.registry_feed_response import RegistryFeedResponse +from adcp.types.generated_poc.core.registry_feed_response import Freshness, RegistryFeedResponse from adcp.types.generated_poc.core.reporting_capabilities import ( DateRangeSupport, ReportingCapabilities, @@ -2029,26 +2029,32 @@ SiTerminateSessionResponse, ) from adcp.types.generated_poc.sponsored_intelligence.si_ui_element import SiUiElement -from adcp.types.generated_poc.tmp.available_package import AvailablePackage -from adcp.types.generated_poc.tmp.context_match_request import ( +from adcp.types.generated_poc.trusted_match.available_package import AvailablePackage +from adcp.types.generated_poc.trusted_match.context_match_request import ( ArtifactRef, ContextMatchRequest, ContextSignals, Sentiment, ) -from adcp.types.generated_poc.tmp.context_match_response import ContextMatchResponse, TargetingKv -from adcp.types.generated_poc.tmp.error import TmpError -from adcp.types.generated_poc.tmp.identity_match_request import ( +from adcp.types.generated_poc.trusted_match.context_match_response import ( + ContextMatchResponse, + TargetingKv, +) +from adcp.types.generated_poc.trusted_match.error import TmpError +from adcp.types.generated_poc.trusted_match.identity_match_request import ( Attestation, Consent, IdentityMatchRequest, SealedCredential, VerificationLevel, ) -from adcp.types.generated_poc.tmp.identity_match_response import IdentityMatchResponse -from adcp.types.generated_poc.tmp.offer import Offer -from adcp.types.generated_poc.tmp.offer_price import OfferPrice -from adcp.types.generated_poc.tmp.provider_registration import ( +from adcp.types.generated_poc.trusted_match.identity_match_response import ( + IdentityMatchResponse, + TmpxProviders, +) +from adcp.types.generated_poc.trusted_match.offer import Offer +from adcp.types.generated_poc.trusted_match.offer_price import OfferPrice +from adcp.types.generated_poc.trusted_match.provider_registration import ( TmpProviderRegistration, TmpProviderRegistration1, TmpProviderRegistration2, @@ -2079,6 +2085,12 @@ from adcp.types.generated_poc.sponsored_intelligence.si_sponsored_context import ( DeclaredBy as _DeclaredByFromSiSponsoredContext, ) +from adcp.types.generated_poc.trusted_match.identity_match_response import ( + TmpxMacro as _TmpxMacroFromIdentityMatchResponse, +) +from adcp.types.generated_poc.trusted_match.provider_registration import ( + TmpxMacro as _TmpxMacroFromProviderRegistration, +) # Backward-compatible adagents authorization variant numbering AuthorizedAgentsUnion = AuthorizedAgents @@ -2775,6 +2787,7 @@ "FrequencyCap", "FrequencyCapScope", "FrequencyCapping", + "Freshness", "From", "FuelType", "GBEnum", @@ -3583,6 +3596,7 @@ "TmpProviderRegistration1", "TmpProviderRegistration2", "TmpResponseType", + "TmpxProviders", "Tone", "Tools", "TotalBudget", @@ -3772,6 +3786,8 @@ "_DeliveryStatusFromGetMediaBuyDeliveryResponse", "_ErrorFromError", "_PackageFromPackage", + "_TmpxMacroFromIdentityMatchResponse", + "_TmpxMacroFromProviderRegistration", ] diff --git a/src/adcp/types/aliases.py b/src/adcp/types/aliases.py index d1aabd0d1..6da08c337 100644 --- a/src/adcp/types/aliases.py +++ b/src/adcp/types/aliases.py @@ -2019,6 +2019,12 @@ class UnknownGroupAsset(_BaseGroupAsset): from adcp.types.generated_poc.sponsored_intelligence.si_sponsored_context import ( DeclaredBy as SiSponsoredContextDeclaredBy, ) +from adcp.types.generated_poc.trusted_match.identity_match_response import ( + TmpxMacro as IdentityMatchTmpxMacro, +) +from adcp.types.generated_poc.trusted_match.provider_registration import ( + TmpxMacro as ProviderRegistrationTmpxMacro, +) # ============================================================================ # EXPORTS @@ -2067,6 +2073,9 @@ class UnknownGroupAsset(_BaseGroupAsset): # DeclaredBy "ProvenanceDeclaredBy", "SiSponsoredContextDeclaredBy", + # TmpxMacro + "IdentityMatchTmpxMacro", + "ProviderRegistrationTmpxMacro", # Unit "DurationUnit", "OverlayUnit", diff --git a/src/adcp/types/generated_poc/adagents.py b/src/adcp/types/generated_poc/adagents.py index d64e90d13..31f9c33a0 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-06-18T11:28:05+00:00 +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations @@ -1270,12 +1270,12 @@ class AdcpAgentsAuthorization2( description='Inline structure variant - contains full agent authorization data', examples=[ { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'authoritative_location': 'https://cdn.example.com/adagents/v2/adagents.json', 'last_updated': '2025-01-15T10:00:00Z', }, { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'properties': [ { 'property_id': 'example_site', @@ -1332,7 +1332,7 @@ class AdcpAgentsAuthorization2( 'last_updated': '2025-01-10T12:00:00Z', }, { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'contact': { 'name': 'Meta Advertising Operations', 'email': 'adops@meta.com', @@ -1401,7 +1401,7 @@ class AdcpAgentsAuthorization2( 'last_updated': '2025-01-10T15:30:00Z', }, { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'contact': {'name': 'Tumblr Advertising'}, 'properties': [ { @@ -1429,7 +1429,7 @@ class AdcpAgentsAuthorization2( 'last_updated': '2025-01-10T16:00:00Z', }, { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'contact': { 'name': 'Example Third-Party Sales Agent', 'email': 'sales@agent.example', @@ -1486,7 +1486,7 @@ class AdcpAgentsAuthorization2( 'last_updated': '2025-01-10T17:00:00Z', }, { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'contact': { 'name': 'Premium News Publisher', 'email': 'adops@news.example.com', @@ -1544,7 +1544,7 @@ class AdcpAgentsAuthorization2( 'last_updated': '2025-01-10T18:00:00Z', }, { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'contact': { 'name': 'Polk Automotive Data', 'email': 'partnerships@polk.com', @@ -1629,12 +1629,12 @@ class AdcpAgentsAuthorization(RootModel[AdcpAgentsAuthorization1 | AdcpAgentsAut description='Declaration of authorized agents for advertising inventory and data signals. Hosted at /.well-known/adagents.json on publisher domains (for properties) or data provider domains (for signals). Can either contain the full structure inline or reference an authoritative URL.', examples=[ { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'authoritative_location': 'https://cdn.example.com/adagents/v2/adagents.json', 'last_updated': '2025-01-15T10:00:00Z', }, { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'properties': [ { 'property_id': 'example_site', @@ -1691,7 +1691,7 @@ class AdcpAgentsAuthorization(RootModel[AdcpAgentsAuthorization1 | AdcpAgentsAut 'last_updated': '2025-01-10T12:00:00Z', }, { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'contact': { 'name': 'Meta Advertising Operations', 'email': 'adops@meta.com', @@ -1760,7 +1760,7 @@ class AdcpAgentsAuthorization(RootModel[AdcpAgentsAuthorization1 | AdcpAgentsAut 'last_updated': '2025-01-10T15:30:00Z', }, { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'contact': {'name': 'Tumblr Advertising'}, 'properties': [ { @@ -1788,7 +1788,7 @@ class AdcpAgentsAuthorization(RootModel[AdcpAgentsAuthorization1 | AdcpAgentsAut 'last_updated': '2025-01-10T16:00:00Z', }, { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'contact': { 'name': 'Example Third-Party Sales Agent', 'email': 'sales@agent.example', @@ -1845,7 +1845,7 @@ class AdcpAgentsAuthorization(RootModel[AdcpAgentsAuthorization1 | AdcpAgentsAut 'last_updated': '2025-01-10T17:00:00Z', }, { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'contact': { 'name': 'Premium News Publisher', 'email': 'adops@news.example.com', @@ -1903,7 +1903,7 @@ class AdcpAgentsAuthorization(RootModel[AdcpAgentsAuthorization1 | AdcpAgentsAut 'last_updated': '2025-01-10T18:00:00Z', }, { - '$schema': '/schemas/3.1.0/adagents.json', + '$schema': '/schemas/3.1.1/adagents.json', 'contact': { 'name': 'Polk Automotive Data', 'email': 'partnerships@polk.com', diff --git a/src/adcp/types/generated_poc/brand/__init__.py b/src/adcp/types/generated_poc/brand/__init__.py index 48095ad5d..9c9917d82 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-06-18T11:28:05+00:00 +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations @@ -2021,23 +2021,23 @@ class BrandDiscovery( description='Brand identity and discovery file. Hosted at /.well-known/brand.json on house domains. Contains the full brand portfolio with identity, creative assets, and digital properties. Brands are identified by house + brand_id (like properties are identified by publisher + property_id). Supports variants: house portfolio (full brand data), brand agent (agent provides brand info via MCP), house redirect (pointer to house domain), or authoritative location redirect.', examples=[ { - '$schema': '/schemas/3.1.0/brand.json', + '$schema': '/schemas/3.1.1/brand.json', 'authoritative_location': 'https://adcontextprotocol.org/brand/abc123/brand.json', }, { - '$schema': '/schemas/3.1.0/brand.json', + '$schema': '/schemas/3.1.1/brand.json', 'house': 'nikeinc.com', 'note': 'Redirect to house domain for full brand portfolio', }, { - '$schema': '/schemas/3.1.0/brand.json', + '$schema': '/schemas/3.1.1/brand.json', 'version': '1.0', 'agents': [ {'type': 'brand', 'url': 'https://agent.acme.com/mcp', 'id': 'acme_brand'} ], }, { - '$schema': '/schemas/3.1.0/brand.json', + '$schema': '/schemas/3.1.1/brand.json', 'version': '1.0', 'house': { 'domain': 'pg.com', @@ -2273,7 +2273,7 @@ class BrandDiscovery( 'last_updated': '2026-01-15T10:00:00Z', }, { - '$schema': '/schemas/3.1.0/brand.json', + '$schema': '/schemas/3.1.1/brand.json', 'version': '1.0', 'house': { 'domain': 'nikeinc.com', @@ -2377,7 +2377,7 @@ class BrandDiscovery( 'last_updated': '2026-01-15T10:00:00Z', }, { - '$schema': '/schemas/3.1.0/brand.json', + '$schema': '/schemas/3.1.1/brand.json', 'version': '1.0', 'house': { 'domain': 'mediavine.com', @@ -2420,7 +2420,7 @@ class BrandDiscovery( 'last_updated': '2026-01-15T10:00:00Z', }, { - '$schema': '/schemas/3.1.0/brand.json', + '$schema': '/schemas/3.1.1/brand.json', 'version': '1.0', 'house': { 'domain': 'nikeinc.com', @@ -2444,7 +2444,7 @@ class BrandDiscovery( 'last_updated': '2026-01-15T10:00:00Z', }, { - '$schema': '/schemas/3.1.0/brand.json', + '$schema': '/schemas/3.1.1/brand.json', 'version': '1.0', 'house': {'domain': 'wpp.com', 'name': 'WPP plc'}, 'brand_refs': [ @@ -2463,7 +2463,7 @@ class BrandDiscovery( 'last_updated': '2026-01-15T10:00:00Z', }, { - '$schema': '/schemas/3.1.0/brand.json', + '$schema': '/schemas/3.1.1/brand.json', 'version': '1.0', 'id': 'converse', 'names': [{'en_US': 'Converse'}], @@ -2474,7 +2474,7 @@ class BrandDiscovery( 'last_updated': '2026-01-15T10:00:00Z', }, { - '$schema': '/schemas/3.1.0/brand.json', + '$schema': '/schemas/3.1.1/brand.json', 'version': '1.0', 'id': 'patagonia', 'names': [{'en_US': 'Patagonia'}], 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 c776fd38f..68c08c71d 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-06-18T11:28:05+00:00 +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations @@ -2427,6 +2427,12 @@ class MediaBuy(AdCPBaseModel): description="Conformance declaration that this seller supports the full proposal lifecycle on get_products: returned proposals are actionable, draft proposals can be finalized with buying_mode: 'refine' + action: 'finalize', and committed proposals can be executed via create_media_buy with proposal_id before expires_at. Buyers SHOULD NOT use this field to decide whether a specific returned proposal is executable; proposal_status is the per-proposal source of truth. A declaration of true opts the seller into proposal-lifecycle grading. When false or absent, conformance runners skip proposal-lifecycle storyboards, but buyers should still honor any proposals the seller actually returns." ), ] = False + governance_aware: Annotated[ + bool | None, + Field( + description='Conformance declaration that this seller consults a registered governance agent (via sync_governance plus an outbound check_governance call) before committing a media buy, and surfaces GOVERNANCE_DENIED when the governance agent denies. A declaration of true opts the seller into governance-denial grading (media_buy_seller/governance_denied, media_buy_seller/governance_denied_recovery). When false or absent, conformance runners skip those storyboards - a seller that does not implement outbound governance consultation is not expected to produce GOVERNANCE_DENIED. This is independent of baseline sync_governance registration, which remains gradeable on its own.' + ), + ] = False propagation_surfaces: Annotated[ list[PropagationSurface] | 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 159a240ab..175f7ef19 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-06-18T11:28:05+00:00 +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations @@ -111,7 +111,7 @@ class VastAsset(RootModel[VastAsset1 | VastAsset2]): root: Annotated[ VastAsset1 | VastAsset2, Field( - description='VAST (Video Ad Serving Template) tag for third-party video ad serving', + description='VAST (Video Ad Serving Template) tag for third-party video ad serving. Unlike the hosted `video` asset, a VAST tag carries no `width`/`height`: a VAST response can return multiple renditions of differing dimensions, and the player selects one per device at serve time, so there is no single width/height for the ad. Dimensional, duration, and codec *constraints* for a placement live on the format/requirements layer, not on this asset.', 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 ca0600b2c..b84c38247 100644 --- a/src/adcp/types/generated_poc/core/assets/video_asset.py +++ b/src/adcp/types/generated_poc/core/assets/video_asset.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/assets/video_asset.json -# timestamp: 2026-05-02T19:36:29+00:00 +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations @@ -64,8 +64,20 @@ class VideoAsset(AdCPBaseModel): ), ] = '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)] + width: Annotated[ + int, + Field( + description="Width in pixels — the video file's intrinsic native width. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no width; see the `vast` asset.)", + ge=1, + ), + ] + height: Annotated[ + int, + Field( + description="Height in pixels — the video file's intrinsic native height. Required: a hosted file always has concrete dimensions. (Tag-delivered video carries no height; see the `vast` asset.)", + ge=1, + ), + ] duration_ms: Annotated[ int | None, Field(description='Video duration in milliseconds', ge=1) ] = None diff --git a/src/adcp/types/generated_poc/core/registry_feed_response.py b/src/adcp/types/generated_poc/core/registry_feed_response.py index e4f29f7cb..b089dae1a 100644 --- a/src/adcp/types/generated_poc/core/registry_feed_response.py +++ b/src/adcp/types/generated_poc/core/registry_feed_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/registry_feed_response.json -# timestamp: 2026-05-28T10:34:10+00:00 +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations @@ -8,11 +8,36 @@ from uuid import UUID from adcp.types.base import AdCPBaseModel -from pydantic import ConfigDict, Field +from pydantic import AwareDatetime, ConfigDict, Field from . import registry_event +class Freshness(AdCPBaseModel): + model_config = ConfigDict( + extra='forbid', + ) + generated_at: Annotated[ + AwareDatetime, Field(description='Server timestamp when this feed page was generated.') + ] + latest_event_created_at: Annotated[ + AwareDatetime | None, + Field( + description='Newest event creation timestamp currently visible in the feed for the requested type filter. Null when no matching event exists inside retention.' + ), + ] + lag_seconds: Annotated[ + int | None, + Field( + description='Seconds between generated_at and latest_event_created_at. Null when no matching event exists.', + ge=0, + ), + ] + retention_days: Annotated[ + int, Field(description='Number of days the registry retains feed cursors and events.', ge=1) + ] + + class RegistryFeedResponse(AdCPBaseModel): model_config = ConfigDict( extra='allow', @@ -27,3 +52,9 @@ class RegistryFeedResponse(AdCPBaseModel): has_more: Annotated[ bool, Field(description='True when more events are immediately available after cursor.') ] + freshness: Annotated[ + Freshness, + Field( + description='Consumer-visible feed freshness metadata for the requested type filter.' + ), + ] diff --git a/src/adcp/types/generated_poc/manifest_schema.py b/src/adcp/types/generated_poc/manifest_schema.py index 0ee1ceea0..402ff491b 100644 --- a/src/adcp/types/generated_poc/manifest_schema.py +++ b/src/adcp/types/generated_poc/manifest_schema.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: manifest.schema.json -# timestamp: 2026-05-02T19:36:29+00:00 +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations @@ -24,7 +24,7 @@ class Protocol(StrEnum): sponsored_intelligence = 'sponsored-intelligence' protocol = 'protocol' compliance = 'compliance' - tmp = 'tmp' + trusted_match = 'trusted-match' a2ui = 'a2ui' @@ -35,7 +35,7 @@ class Tools(AdCPBaseModel): protocol: Annotated[ Protocol, Field( - description='The protocol surface this tool belongs to. Derived from the source directory: media-buy, signals, governance, account, creative, brand, content-standards, property, collection, sponsored-intelligence, protocol, compliance, tmp.' + description='The protocol surface this tool belongs to. Derived from the source directory: media-buy, signals, governance, account, creative, brand, content-standards, property, collection, sponsored-intelligence, protocol, compliance, trusted-match.' ), ] mutating: Annotated[ 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 d93feaa24..c01f24ed3 100644 --- a/src/adcp/types/generated_poc/media_buy/get_products_request.py +++ b/src/adcp/types/generated_poc/media_buy/get_products_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_request.json -# timestamp: 2026-06-12T11:05:47+00:00 +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations @@ -230,7 +230,12 @@ class GetProductsRequest(AdcpVersionEnvelope): description='Optional webhook configuration for async terminal completion/failure notifications on curated discovery. Meaningful only for `buying_mode: "brief"` and `buying_mode: "refine"` requests that enter the async lifecycle. Submitted envelopes with `task_id` remain pollable through `get_task_status` (legacy `tasks/get`) whether or not this field is present. If a brief/refine request includes this field and the seller returns a Submitted envelope, the seller MUST deliver at least the terminal completion/failure notification to the configured URL; intermediate progress notifications are MAY. If the seller cannot honor the webhook channel, it MUST reject the request with a structured error instead of silently accepting. This field does not change wholesale timing semantics: sellers MUST NOT route `buying_mode: "wholesale"` requests through the async/Submitted arm or emit async delivery solely because `push_notification_config` is present; partial wholesale completion is reported via `incomplete[]`.' ), ] = None - pagination: pagination_request.PaginationRequest | None = None + pagination: Annotated[ + pagination_request.PaginationRequest | None, + Field( + description="Cursor-based pagination controls for get_products. Valid in all buying modes. In brief mode, pagination bounds the seller's returned products[] for the curated answer to the brief and is not an exhaustive catalog-enumeration contract. In refine mode, pagination bounds the refined products[] result implied by refine[] and filters; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope. In wholesale mode, pagination walks the wholesale product feed and may be combined with wholesale feed versioning." + ), + ] = None if_wholesale_feed_version: Annotated[ str | None, Field( 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 69fe4abdf..1d055e5f3 100644 --- a/src/adcp/types/generated_poc/media_buy/get_products_response.py +++ b/src/adcp/types/generated_poc/media_buy/get_products_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_response.json -# timestamp: 2026-05-30T17:30:49+00:00 +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations @@ -287,7 +287,12 @@ class GetProductsResponse(AdcpVersionEnvelope, ProtocolEnvelope): ], ), ] = None - pagination: pagination_response.PaginationResponse | None = None + pagination: Annotated[ + pagination_response.PaginationResponse | None, + Field( + description="Cursor metadata for paginated get_products responses. In brief/refine mode, continuation pages bound returned products[] for the seller's curated or refined answer; proposals may accompany a page as plan metadata but are not independently counted by this pagination envelope, and pagination does not convert the response into an exhaustive feed contract. In wholesale mode, continuation pages walk the wholesale product feed." + ), + ] = None wholesale_feed_version: Annotated[ str | None, Field( 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 de3dffbc5..53c28c755 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-06-18T11:28:05+00:00 +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations @@ -1177,6 +1177,12 @@ class MediaBuy(AdCPBaseModel): description="Conformance declaration that this seller supports the full proposal lifecycle on get_products: returned proposals are actionable, draft proposals can be finalized with buying_mode: 'refine' + action: 'finalize', and committed proposals can be executed via create_media_buy with proposal_id before expires_at. Buyers SHOULD NOT use this field to decide whether a specific returned proposal is executable; proposal_status is the per-proposal source of truth. A declaration of true opts the seller into proposal-lifecycle grading. When false or absent, conformance runners skip proposal-lifecycle storyboards, but buyers should still honor any proposals the seller actually returns." ), ] = False + governance_aware: Annotated[ + bool | None, + Field( + description='Conformance declaration that this seller consults a registered governance agent (via sync_governance plus an outbound check_governance call) before committing a media buy, and surfaces GOVERNANCE_DENIED when the governance agent denies. A declaration of true opts the seller into governance-denial grading (media_buy_seller/governance_denied, media_buy_seller/governance_denied_recovery). When false or absent, conformance runners skip those storyboards - a seller that does not implement outbound governance consultation is not expected to produce GOVERNANCE_DENIED. This is independent of baseline sync_governance registration, which remains gradeable on its own.' + ), + ] = False propagation_surfaces: Annotated[ list[PropagationSurface] | 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 deleted file mode 100644 index a640936fb..000000000 --- a/src/adcp/types/generated_poc/tmp/identity_match_response.py +++ /dev/null @@ -1,45 +0,0 @@ -# generated by datamodel-codegen: -# filename: tmp/identity_match_response.json -# timestamp: 2026-05-22T13:15:12+00:00 - -from __future__ import annotations - -from typing import Annotated, Literal - -from pydantic import ConfigDict, Field - -from ..core.protocol_envelope import ProtocolEnvelope -from ..core.version_envelope import AdcpVersionEnvelope - - -class IdentityMatchResponse(AdcpVersionEnvelope, ProtocolEnvelope): - model_config = ConfigDict( - extra='allow', - ) - 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') - ] - eligible_package_ids: Annotated[ - list[str], - Field( - description='Package IDs the user is eligible for. Packages not listed are ineligible.' - ), - ] - serve_window_sec: Annotated[ - int, - Field( - description="Per-package single-shot fcap window, in seconds. After serving the user one impression on each eligible package within this window, the publisher MUST re-query Identity Match before serving from those packages again. This is NOT a router response cache TTL — it is a buyer-asserted serve throttle. Multi-impression frequency caps are handled separately by the buyer's impression tracker, which writes cap-fire events to the IdentityMatch cap-state store at the boundary regardless of this window. Maximum 300 — longer windows reduce IdentityMatch load but coarsen fcap granularity below what most campaigns require.", - ge=1, - le=300, - ), - ] - tmpx: Annotated[ - str | None, - Field( - description="HPKE-encrypted exposure token containing the resolved user identity tokens. The publisher substitutes this into creative tracking URLs as {TMPX}. The buyer's impression pixel receives the token at serve time, enabling real-time per-user frequency state updates. Wire format: kid.base64url_nopad(ciphertext) — unpadded base64url per RFC 4648 section 5 (no = characters). Publishers MUST treat this value as opaque pass-through data." - ), - ] = None diff --git a/src/adcp/types/generated_poc/tmp/__init__.py b/src/adcp/types/generated_poc/trusted_match/__init__.py similarity index 60% rename from src/adcp/types/generated_poc/tmp/__init__.py rename to src/adcp/types/generated_poc/trusted_match/__init__.py index b6f833879..a20dd31c4 100644 --- a/src/adcp/types/generated_poc/tmp/__init__.py +++ b/src/adcp/types/generated_poc/trusted_match/__init__.py @@ -1,3 +1,3 @@ # generated by datamodel-codegen: # filename: .schema_temp -# timestamp: 2026-04-02T22:34:46+00:00 +# timestamp: 2026-07-01T04:30:58+00:00 diff --git a/src/adcp/types/generated_poc/tmp/available_package.py b/src/adcp/types/generated_poc/trusted_match/available_package.py similarity index 94% rename from src/adcp/types/generated_poc/tmp/available_package.py rename to src/adcp/types/generated_poc/trusted_match/available_package.py index e6875d0d0..30e22e64d 100644 --- a/src/adcp/types/generated_poc/tmp/available_package.py +++ b/src/adcp/types/generated_poc/trusted_match/available_package.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: -# filename: tmp/available_package.json -# timestamp: 2026-05-02T19:36:29+00:00 +# filename: trusted_match/available_package.json +# timestamp: 2026-07-01T04:30:58+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/trusted_match/context_match_request.py similarity index 99% rename from src/adcp/types/generated_poc/tmp/context_match_request.py rename to src/adcp/types/generated_poc/trusted_match/context_match_request.py index cb515a661..85483b2f5 100644 --- a/src/adcp/types/generated_poc/tmp/context_match_request.py +++ b/src/adcp/types/generated_poc/trusted_match/context_match_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: -# filename: tmp/context_match_request.json -# timestamp: 2026-06-12T11:05:47+00:00 +# filename: trusted_match/context_match_request.json +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/tmp/context_match_response.py b/src/adcp/types/generated_poc/trusted_match/context_match_response.py similarity index 95% rename from src/adcp/types/generated_poc/tmp/context_match_response.py rename to src/adcp/types/generated_poc/trusted_match/context_match_response.py index 18d69f854..69defccf3 100644 --- a/src/adcp/types/generated_poc/tmp/context_match_response.py +++ b/src/adcp/types/generated_poc/trusted_match/context_match_response.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: -# filename: tmp/context_match_response.json -# timestamp: 2026-05-22T13:15:12+00:00 +# filename: trusted_match/context_match_response.json +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/tmp/error.py b/src/adcp/types/generated_poc/trusted_match/error.py similarity index 94% rename from src/adcp/types/generated_poc/tmp/error.py rename to src/adcp/types/generated_poc/trusted_match/error.py index 6951772d2..8130a0bc5 100644 --- a/src/adcp/types/generated_poc/tmp/error.py +++ b/src/adcp/types/generated_poc/trusted_match/error.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: -# filename: tmp/error.json -# timestamp: 2026-05-02T19:36:29+00:00 +# filename: trusted_match/error.json +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/tmp/identity_match_request.py b/src/adcp/types/generated_poc/trusted_match/identity_match_request.py similarity index 99% rename from src/adcp/types/generated_poc/tmp/identity_match_request.py rename to src/adcp/types/generated_poc/trusted_match/identity_match_request.py index 2469e58c6..630663da0 100644 --- a/src/adcp/types/generated_poc/tmp/identity_match_request.py +++ b/src/adcp/types/generated_poc/trusted_match/identity_match_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: -# filename: tmp/identity_match_request.json -# timestamp: 2026-06-12T11:05:47+00:00 +# filename: trusted_match/identity_match_request.json +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/trusted_match/identity_match_response.py b/src/adcp/types/generated_poc/trusted_match/identity_match_response.py new file mode 100644 index 000000000..b9d1ba70e --- /dev/null +++ b/src/adcp/types/generated_poc/trusted_match/identity_match_response.py @@ -0,0 +1,115 @@ +# generated by datamodel-codegen: +# filename: trusted_match/identity_match_response.json +# timestamp: 2026-07-01T04:30:58+00:00 + +from __future__ import annotations + +import re + +from typing import Annotated, Literal + +from adcp.types.base import AdCPBaseModel +from pydantic import ConfigDict, Field, model_validator + +from ..core.protocol_envelope import ProtocolEnvelope +from ..core.version_envelope import AdcpVersionEnvelope + + +_PROVIDER_ID_PATTERN = re.compile(r'^[A-Za-z0-9_]{1,64}$') + + +class TmpxMacro(AdCPBaseModel): + model_config = ConfigDict( + extra='forbid', + ) + name: Annotated[ + str, + Field( + description="Macro name as configured in the publisher's ad server (e.g. `PIN_TMPX_1`). MUST appear in the emitting provider's registered `tmpx_macros` list. Provider-namespaced so the publisher can target distinct slots per provider.", + max_length=64, + min_length=1, + pattern='^[A-Z][A-Z0-9_]*$', + ), + ] + value: Annotated[ + str, + Field( + description='Opaque, URL-safe wire string the publisher substitutes verbatim into the named macro slot. Publishers MUST NOT parse, decode, or transform this value. The protocol fixes the wire format so platforms interoperate; a platform that can carry raw bytes MAY optimize privately but the wire contract remains the URL-safe string.', + max_length=1024, + min_length=1, + ), + ] + + +class TmpxProviders(AdCPBaseModel): + model_config = ConfigDict( + extra='forbid', + ) + macros: Annotated[ + list[TmpxMacro], + Field( + description="Ordered TMPX macro/value pairs for this provider. Names MUST match the provider's registered `tmpx_macros`.", + max_length=2, + min_length=1, + ), + ] + + +class IdentityMatchResponse(AdcpVersionEnvelope, ProtocolEnvelope): + model_config = ConfigDict( + extra='allow', + ) + 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') + ] + eligible_package_ids: Annotated[ + list[str], + Field( + description='Package IDs the user is eligible for. Packages not listed are ineligible.' + ), + ] + serve_window_sec: Annotated[ + int, + Field( + description="Per-package single-shot fcap window, in seconds. After serving the user one impression on each eligible package within this window, the publisher MUST re-query Identity Match before serving from those packages again. This is NOT a router response cache TTL — it is a buyer-asserted serve throttle. Multi-impression frequency caps are handled separately by the buyer's impression tracker, which writes cap-fire events to the IdentityMatch cap-state store at the boundary regardless of this window. Maximum 300 — longer windows reduce IdentityMatch load but coarsen fcap granularity below what most campaigns require.", + ge=1, + le=300, + ), + ] + tmpx: Annotated[ + str | None, + Field( + description='DEPRECATED in favor of tmpx_providers. Routers MAY continue to populate this field for back-compat with consumers that only know the single-token shape; when both fields are present, tmpx_providers is authoritative. Single HPKE-encrypted exposure token containing the resolved user identity tokens. Wire format: kid.base64url_nopad(ciphertext) — unpadded base64url per RFC 4648 section 5 (no = characters). Publishers MUST treat this value as opaque pass-through data. Removed in 4.0.' + ), + ] = None + tmpx_macros: Annotated[ + list[TmpxMacro] | None, + Field( + description="Provider-emitted: the identity agent's ordered TMPX chunks paired with the macro name each chunk fills. Macro names MUST be drawn from the provider's registered `tmpx_macros` list (provider-registration.json) and appear in the same order — names are part of operational setup, not protocol-synthesized. Capped at 2 chunks in v1; the cap MAY rise without a shape change. Each `value` is an opaque URL-safe wire string the publisher substitutes verbatim into the matching ad-server macro slot — publishers MUST NOT parse, decode, transform, or choose an encoding. The router collects entries from every provider that emits them into `tmpx_providers`, keyed by provider_id; consumers reading the merged response SHOULD consume `tmpx_providers` and ignore `tmpx_macros` at the root.", + max_length=2, + min_length=1, + ), + ] = None + tmpx_providers: Annotated[ + dict[str, TmpxProviders] | None, + Field( + description="Router-populated: TMPX macro/value pairs grouped by the originating identity provider's provider_id, so the publisher fires each provider's tokens through that provider's specific ad-server macros (configured per provider in GAM / VAST URL / DOOH play log). Each entry's `macros[]` is a copy of the provider's emitted `tmpx_macros` ordered list. SHAPE CHANGE: was `Map` in the experimental surface that shipped in #5689; now `Map` to carry exact macro/value pairs and support multi-chunk TMPX. Sanctioned by the experimental contract (`x-status: experimental` on this schema). Required by router conformance when any identity provider emitted TMPX in this request; collapsing per-provider tokens into a single string loses attribution and breaks per-provider impression accounting. Map keys MUST be valid provider_ids registered for this fan-out. Publishers MUST traffic only the macro names the response advertises; macro names MUST NOT be derived from provider_id at runtime." + ), + ] = None + + @model_validator(mode='after') + def _validate_tmpx_provider_ids(self) -> IdentityMatchResponse: + if self.tmpx_providers is None: + return self + invalid = [ + provider_id + for provider_id in self.tmpx_providers + if not _PROVIDER_ID_PATTERN.fullmatch(provider_id) + ] + if invalid: + raise ValueError('tmpx_providers keys must be valid provider_id values') + return self diff --git a/src/adcp/types/generated_poc/tmp/offer.py b/src/adcp/types/generated_poc/trusted_match/offer.py similarity index 97% rename from src/adcp/types/generated_poc/tmp/offer.py rename to src/adcp/types/generated_poc/trusted_match/offer.py index 761a729d0..368e37c96 100644 --- a/src/adcp/types/generated_poc/tmp/offer.py +++ b/src/adcp/types/generated_poc/trusted_match/offer.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: -# filename: tmp/offer.json -# timestamp: 2026-05-02T19:36:29+00:00 +# filename: trusted_match/offer.json +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/tmp/offer_price.py b/src/adcp/types/generated_poc/trusted_match/offer_price.py similarity index 89% rename from src/adcp/types/generated_poc/tmp/offer_price.py rename to src/adcp/types/generated_poc/trusted_match/offer_price.py index 8c98ca231..410c744df 100644 --- a/src/adcp/types/generated_poc/tmp/offer_price.py +++ b/src/adcp/types/generated_poc/trusted_match/offer_price.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: -# filename: tmp/offer_price.json -# timestamp: 2026-05-02T19:36:29+00:00 +# filename: trusted_match/offer_price.json +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations diff --git a/src/adcp/types/generated_poc/tmp/provider_registration.py b/src/adcp/types/generated_poc/trusted_match/provider_registration.py similarity index 61% rename from src/adcp/types/generated_poc/tmp/provider_registration.py rename to src/adcp/types/generated_poc/trusted_match/provider_registration.py index 64738f86d..f8a88edff 100644 --- a/src/adcp/types/generated_poc/tmp/provider_registration.py +++ b/src/adcp/types/generated_poc/trusted_match/provider_registration.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: -# filename: tmp/provider_registration.json -# timestamp: 2026-06-01T00:32:59+00:00 +# filename: trusted_match/provider_registration.json +# timestamp: 2026-07-01T04:30:58+00:00 from __future__ import annotations @@ -9,7 +9,7 @@ from uuid import UUID from adcp.types.base import AdCPBaseModel -from pydantic import AnyUrl, ConfigDict, Field, RootModel +from pydantic import AnyUrl, ConfigDict, Field, RootModel, field_validator, model_validator from ..enums import uid_type @@ -18,6 +18,10 @@ class Country(RootModel[str]): root: Annotated[str, Field(pattern='^[A-Z]{2}$')] +class TmpxMacro(RootModel[str]): + root: Annotated[str, Field(max_length=64, min_length=1, pattern='^[A-Z][A-Z0-9_]*$')] + + class Status(StrEnum): active = 'active' inactive = 'inactive' @@ -31,7 +35,10 @@ class TmpProviderRegistration1(AdCPBaseModel): provider_id: Annotated[ str, Field( - description="Stable identifier for this provider registration. Used in logs, metrics, and cache keys. Publishers assign this — it is not the provider's agent_url." + description="Stable identifier for this provider registration. Used in logs, metrics, cache keys, and as the key in `tmpx_providers` on the identity-match response so the publisher can route each provider's TMPX `macros[]` to that provider's pre-configured ad-server slots (names registered in `tmpx_macros` below — macro names MUST NOT be derived from `provider_id` at runtime). Publishers assign this — it is not the provider's agent_url. Charset is constrained to a safe alphanumeric/underscore set so the value can appear in operational surfaces (logs, metrics, dashboards) without quoting.", + max_length=64, + min_length=1, + pattern='^[A-Za-z0-9_]+$', ), ] endpoint: Annotated[ @@ -82,6 +89,14 @@ class TmpProviderRegistration1(AdCPBaseModel): ge=0, ), ] = 0 + tmpx_macros: Annotated[ + list[TmpxMacro] | None, + Field( + description='Stable, provider-namespaced ad-server macro names this provider\'s TMPX response fills, ordered. Publishers traffic these exact names in their ad server (GAM key-values, VAST URL macros, DOOH play-log fields); the router places each provider\'s TMPX chunks into the matching slots on the identity-match response (`tmpx_providers[provider_id].macros[]`). Names MUST be provider-namespaced so publishers can configure distinct macros per provider (e.g. `PIN_TMPX_1`, `PIN_TMPX_2` for one provider; `NOVA_TMPX_1` for another). Ordered so multi-chunk TMPX values (when the opaque token exceeds one macro slot) are placed deterministically. Capped at 2 entries in v1; the cap MAY be raised in a later version without a shape change. A provider that emits TMPX on its identity-match response (populates `tmpx_macros[]` there) MUST also register this list — otherwise the router has no slot names to forward — but the schema cannot enforce this because "emits TMPX" is not a schema-visible predicate. Providers that do not emit TMPX omit this field.', + max_length=2, + min_length=1, + ), + ] = None status: Annotated[ Status | None, Field( @@ -90,6 +105,23 @@ class TmpProviderRegistration1(AdCPBaseModel): ] = Status.active + @field_validator('endpoint') + @classmethod + def _require_https_endpoint(cls, value: AnyUrl) -> AnyUrl: + if value.scheme != 'https': + raise ValueError('endpoint must use https') + return value + + @model_validator(mode='after') + def _require_identity_match_dimensions(self) -> TmpProviderRegistration1: + if self.identity_match is True: + if not self.countries: + raise ValueError('countries is required when identity_match is true') + if not self.uid_types: + raise ValueError('uid_types is required when identity_match is true') + return self + + class TmpProviderRegistration2(AdCPBaseModel): model_config = ConfigDict( extra='forbid', @@ -97,7 +129,10 @@ class TmpProviderRegistration2(AdCPBaseModel): provider_id: Annotated[ str, Field( - description="Stable identifier for this provider registration. Used in logs, metrics, and cache keys. Publishers assign this — it is not the provider's agent_url." + description="Stable identifier for this provider registration. Used in logs, metrics, cache keys, and as the key in `tmpx_providers` on the identity-match response so the publisher can route each provider's TMPX `macros[]` to that provider's pre-configured ad-server slots (names registered in `tmpx_macros` below — macro names MUST NOT be derived from `provider_id` at runtime). Publishers assign this — it is not the provider's agent_url. Charset is constrained to a safe alphanumeric/underscore set so the value can appear in operational surfaces (logs, metrics, dashboards) without quoting.", + max_length=64, + min_length=1, + pattern='^[A-Za-z0-9_]+$', ), ] endpoint: Annotated[ @@ -149,6 +184,14 @@ class TmpProviderRegistration2(AdCPBaseModel): ge=0, ), ] = 0 + tmpx_macros: Annotated[ + list[TmpxMacro] | None, + Field( + description='Stable, provider-namespaced ad-server macro names this provider\'s TMPX response fills, ordered. Publishers traffic these exact names in their ad server (GAM key-values, VAST URL macros, DOOH play-log fields); the router places each provider\'s TMPX chunks into the matching slots on the identity-match response (`tmpx_providers[provider_id].macros[]`). Names MUST be provider-namespaced so publishers can configure distinct macros per provider (e.g. `PIN_TMPX_1`, `PIN_TMPX_2` for one provider; `NOVA_TMPX_1` for another). Ordered so multi-chunk TMPX values (when the opaque token exceeds one macro slot) are placed deterministically. Capped at 2 entries in v1; the cap MAY be raised in a later version without a shape change. A provider that emits TMPX on its identity-match response (populates `tmpx_macros[]` there) MUST also register this list — otherwise the router has no slot names to forward — but the schema cannot enforce this because "emits TMPX" is not a schema-visible predicate. Providers that do not emit TMPX omit this field.', + max_length=2, + min_length=1, + ), + ] = None status: Annotated[ Status | None, Field( @@ -157,6 +200,23 @@ class TmpProviderRegistration2(AdCPBaseModel): ] = Status.active + @field_validator('endpoint') + @classmethod + def _require_https_endpoint(cls, value: AnyUrl) -> AnyUrl: + if value.scheme != 'https': + raise ValueError('endpoint must use https') + return value + + @model_validator(mode='after') + def _require_identity_match_dimensions(self) -> TmpProviderRegistration2: + if self.identity_match is True: + if not self.countries: + raise ValueError('countries is required when identity_match is true') + if not self.uid_types: + raise ValueError('uid_types is required when identity_match is true') + return self + + class TmpProviderRegistration(RootModel[TmpProviderRegistration1 | TmpProviderRegistration2]): root: Annotated[ TmpProviderRegistration1 | TmpProviderRegistration2, diff --git a/tests/fixtures/public_api_snapshot.json b/tests/fixtures/public_api_snapshot.json index 0b852823b..2ed2d0cc5 100644 --- a/tests/fixtures/public_api_snapshot.json +++ b/tests/fixtures/public_api_snapshot.json @@ -213,6 +213,7 @@ "HtmlPreviewRender", "IdentityMatchRequest", "IdentityMatchResponse", + "IdentityMatchTmpxMacro", "InlineDaastAsset", "InlineVastAsset", "KellerType", @@ -300,6 +301,7 @@ "ProvidePerformanceFeedbackResponse", "ProvidePerformanceFeedbackResponse1", "ProvidePerformanceFeedbackSuccessResponse", + "ProviderRegistrationTmpxMacro", "PublisherDivergence", "PublisherProperties", "PublisherPropertiesAll", @@ -817,6 +819,7 @@ "Identifier", "IdentityMatchRequest", "IdentityMatchResponse", + "IdentityMatchTmpxMacro", "ImageContent", "ImageFormatAsset", "ImageFormatGroupAsset", @@ -966,6 +969,7 @@ "ProvidePerformanceFeedbackResponse", "ProvidePerformanceFeedbackResponse1", "ProvidePerformanceFeedbackSuccessResponse", + "ProviderRegistrationTmpxMacro", "PublisherDomain", "PublisherIdentifierTypes", "PublisherProperties", diff --git a/tests/test_collision_aliases.py b/tests/test_collision_aliases.py index cf1589b55..641602bfd 100644 --- a/tests/test_collision_aliases.py +++ b/tests/test_collision_aliases.py @@ -60,6 +60,9 @@ # DeclaredBy — 2 variants ("ProvenanceDeclaredBy", "core.provenance", "DeclaredBy"), ("SiSponsoredContextDeclaredBy", "sponsored_intelligence.si_sponsored_context", "DeclaredBy"), + # TmpxMacro — 2 variants + ("IdentityMatchTmpxMacro", "trusted_match.identity_match_response", "TmpxMacro"), + ("ProviderRegistrationTmpxMacro", "trusted_match.provider_registration", "TmpxMacro"), # Unit — 4 variants ("DurationUnit", "core.duration", "Unit"), ("OverlayUnit", "core.overlay", "Unit"), @@ -164,6 +167,9 @@ def test_distinct_variants_are_distinct_classes() -> None: # DeclaredBy: provenance and SI sponsored context use different role enums. assert a.ProvenanceDeclaredBy is not a.SiSponsoredContextDeclaredBy + # TmpxMacro: emitted macro/value pairs vs registered macro-name strings. + assert a.IdentityMatchTmpxMacro is not a.ProviderRegistrationTmpxMacro + # Unit: four distinct unit enums. assert len({a.DurationUnit, a.OverlayUnit, a.RealEstateUnit, a.VehicleUnit}) == 4 @@ -195,3 +201,11 @@ def test_listing_creative_is_the_rich_shape() -> None: assert "assets" in listing_fields assert "assignments" in listing_fields assert listing_fields != delivery_fields + + +def test_tmpx_macro_aliases_cover_distinct_shapes() -> None: + """TMPX macro aliases distinguish emitted values from registered names.""" + from adcp.types import aliases as a + + assert set(a.IdentityMatchTmpxMacro.model_fields) == {"name", "value"} + assert set(a.ProviderRegistrationTmpxMacro.model_fields) == {"root"} diff --git a/tests/test_trusted_match_validation.py b/tests/test_trusted_match_validation.py new file mode 100644 index 000000000..2c59f3487 --- /dev/null +++ b/tests/test_trusted_match_validation.py @@ -0,0 +1,73 @@ +import pytest +from pydantic import ValidationError + +from adcp.types.generated_poc.trusted_match.identity_match_response import ( + IdentityMatchResponse, +) +from adcp.types.generated_poc.trusted_match.provider_registration import ( + TmpProviderRegistration, +) + + +def test_provider_registration_requires_identity_dimensions_when_identity_match_enabled(): + with pytest.raises(ValidationError, match="countries is required"): + TmpProviderRegistration.model_validate( + { + "provider_id": "provider_1", + "endpoint": "https://example.com", + "identity_match": True, + } + ) + + +def test_provider_registration_rejects_non_https_endpoint(): + with pytest.raises(ValidationError, match="endpoint must use https"): + TmpProviderRegistration.model_validate( + { + "provider_id": "provider_1", + "endpoint": "http://example.com", + "context_match": True, + } + ) + + +def test_provider_registration_accepts_valid_identity_registration(): + registration = TmpProviderRegistration.model_validate( + { + "provider_id": "provider_1", + "endpoint": "https://example.com", + "identity_match": True, + "countries": ["US"], + "uid_types": ["uid2"], + } + ) + + assert registration.provider_id == "provider_1" + + +def test_identity_match_response_rejects_invalid_tmpx_provider_ids(): + with pytest.raises(ValidationError, match="tmpx_providers keys"): + IdentityMatchResponse.model_validate( + { + "request_id": "request_1", + "eligible_package_ids": [], + "serve_window_sec": 60, + "tmpx_providers": { + "bad provider!": {"macros": [{"name": "PIN_TMPX_1", "value": "abc"}]} + }, + } + ) + + +def test_identity_match_response_accepts_valid_tmpx_provider_ids(): + response = IdentityMatchResponse.model_validate( + { + "request_id": "request_1", + "eligible_package_ids": [], + "serve_window_sec": 60, + "tmpx_providers": {"provider_1": {"macros": [{"name": "PIN_TMPX_1", "value": "abc"}]}}, + } + ) + + assert response.tmpx_providers is not None + assert "provider_1" in response.tmpx_providers From eb9e7acd6da4de49811a784f039850c89a62aae4 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Wed, 1 Jul 2026 08:10:51 +0100 Subject: [PATCH 2/4] fix(codegen): normalize constrained dict keys --- scripts/generate_types.py | 2 ++ scripts/post_generate_fixes.py | 22 ++++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/scripts/generate_types.py b/scripts/generate_types.py index 95ff44eb8..e44b42db3 100755 --- a/scripts/generate_types.py +++ b/scripts/generate_types.py @@ -363,6 +363,8 @@ def _run_datamodel_codegen(input_path: Path, output_path: Path) -> subprocess.Co "--set-default-enum-member", "--enum-field-as-literal", "one", + "--formatters", + "ruff-format", ] return subprocess.run( diff --git a/scripts/post_generate_fixes.py b/scripts/post_generate_fixes.py index 9b6d6523d..0c07d1779 100644 --- a/scripts/post_generate_fixes.py +++ b/scripts/post_generate_fixes.py @@ -624,10 +624,12 @@ def _find_indented_field_block(content: str, field_name: str) -> tuple[int, int] def fix_constr_type_annotations(): - """Replace constr(pattern=...) with Annotated[str, StringConstraints(pattern=...)] in generated files. + """Normalize constrained string annotations in generated files. - datamodel-code-generator uses constr(pattern=...) as dict key types, but mypy's - Pydantic v2 plugin rejects this form. The correct form is Annotated[str, StringConstraints(...)]. + datamodel-code-generator has emitted both ``constr(pattern=...)`` and bare + ``StringConstraints(...)`` as dict key types across releases. Pydantic's + schema generation expects the constraint metadata to be attached to ``str`` + via ``Annotated[str, StringConstraints(...)]``. """ fixed_count = 0 @@ -635,7 +637,7 @@ def fix_constr_type_annotations(): with open(py_file) as f: content = f.read() - if "constr(pattern=" not in content: + if "constr(pattern=" not in content and "dict[StringConstraints(" not in content: continue original = content @@ -650,15 +652,23 @@ def fix_constr_type_annotations(): # Replace 'constr' in imports with 'StringConstraints' content = re.sub(r"\bconstr\b", "StringConstraints", content) + # Replace dict[StringConstraints(...), T] with + # dict[Annotated[str, StringConstraints(...)], T]. + content = re.sub( + r"dict\[StringConstraints\((.*?)\),", + r"dict[Annotated[str, StringConstraints(\1)],", + content, + ) + if content != original: with open(py_file, "w") as f: f.write(content) fixed_count += 1 if fixed_count > 0: - print(f" Replaced constr(pattern=...) with StringConstraints in {fixed_count} file(s)") + print(f" Normalized constrained string annotations in {fixed_count} file(s)") else: - print(" No constr(pattern=...) annotations needed fixing") + print(" No constrained string annotations needed fixing") # Types to unwrap from RootModel to Union type alias. From cd6630c6fbcf797148d458c149eec17b57ef338b Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Wed, 1 Jul 2026 08:46:36 +0100 Subject: [PATCH 3/4] fix(codegen): skip pruned bundled schemas --- scripts/generate_types.py | 82 +++++----- src/adcp/types/_generated.py | 144 ++++++++--------- .../types/generated_poc/a2ui/si_catalog.py | 12 +- .../account/sync_accounts_request.py | 6 +- .../get_adcp_capabilities_response.py | 40 ++--- src/adcp/types/generated_poc/core/format.py | 146 +++++++++--------- .../generated_poc/core/optimization_goal.py | 20 +-- .../types/generated_poc/core/provenance.py | 6 +- .../types/generated_poc/core/signal_id.py | 10 +- .../types/generated_poc/core/signal_ref.py | 12 +- .../governance/sync_plans_response.py | 6 +- .../media_buy/get_products_request.py | 8 +- .../get_adcp_capabilities_response.py | 16 +- .../si_sponsored_context_receipt.py | 6 +- 14 files changed, 254 insertions(+), 260 deletions(-) diff --git a/scripts/generate_types.py b/scripts/generate_types.py index e44b42db3..00a63b159 100755 --- a/scripts/generate_types.py +++ b/scripts/generate_types.py @@ -363,8 +363,6 @@ def _run_datamodel_codegen(input_path: Path, output_path: Path) -> subprocess.Co "--set-default-enum-member", "--enum-field-as-literal", "one", - "--formatters", - "ruff-format", ] return subprocess.run( @@ -379,57 +377,56 @@ def _print_codegen_output(result: subprocess.CompletedProcess[str]) -> None: print(result.stdout) -def _generate_split_bundled_media_buy(input_dir: Path) -> bool: - """Generate bundled/media_buy schemas separately. +def _restore_optional_temp_dir(source: Path, target: Path) -> None: + if source.exists(): + target.parent.mkdir(parents=True, exist_ok=True) + shutil.move(str(source), str(target)) - The fully bundled media-buy directory is large enough that - datamodel-code-generator can spend minutes trying to deduplicate the - combined inline graph. Generating those bundled message schemas one file - at a time preserves the import surface while keeping regeneration bounded. - """ - split_dir = input_dir / "bundled" / "media_buy" - if not split_dir.exists(): - return True - - output_dir = OUTPUT_DIR / "bundled" / "media_buy" - output_dir.mkdir(parents=True, exist_ok=True) - for package_dir in (OUTPUT_DIR / "bundled", output_dir): - init_file = package_dir / "__init__.py" - init_file.touch(exist_ok=True) - - print(f"Generating split bundled media-buy types from {split_dir}...") - for schema_file in sorted(split_dir.glob("*.json")): - output_file = output_dir / f"{schema_file.stem}.py" - print(f" {schema_file.name}") - result = _run_datamodel_codegen(schema_file, output_file) - _print_codegen_output(result) - if result.returncode != 0: - print("\n✗ Split bundled media-buy generation failed:", file=sys.stderr) - print(result.stderr, file=sys.stderr) - return False - return True +def _hold_unused_bundled_dirs(input_dir: Path) -> Path: + """Move bundled subtrees that are pruned later out of the generator input.""" + bundled_dir = input_dir / BUNDLED_DIR_NAME + held_bundled_dir = input_dir.parent / f"{input_dir.name}_bundled_held" + + if held_bundled_dir.exists(): + shutil.rmtree(held_bundled_dir) + if not bundled_dir.exists(): + return held_bundled_dir + + shutil.move(str(bundled_dir), str(held_bundled_dir)) + + protocol_dir = held_bundled_dir / "protocol" + if protocol_dir.exists(): + bundled_dir.mkdir(parents=True, exist_ok=True) + shutil.move(str(protocol_dir), str(bundled_dir / "protocol")) + + return held_bundled_dir + + +def _restore_unused_bundled_dirs(input_dir: Path, held_bundled_dir: Path) -> None: + bundled_dir = input_dir / BUNDLED_DIR_NAME + protocol_dir = bundled_dir / "protocol" + + if protocol_dir.exists(): + held_bundled_dir.mkdir(parents=True, exist_ok=True) + shutil.move(str(protocol_dir), str(held_bundled_dir / "protocol")) + + if bundled_dir.exists() and not any(bundled_dir.iterdir()): + bundled_dir.rmdir() + + _restore_optional_temp_dir(held_bundled_dir, bundled_dir) def generate_types(input_dir: Path): """Generate types using datamodel-code-generator.""" print(f"Generating types from {input_dir}...") - split_dir = input_dir / "bundled" / "media_buy" - held_split_dir = input_dir.parent / f"{input_dir.name}_bundled_media_buy_split" - - if held_split_dir.exists(): - shutil.rmtree(held_split_dir) - - if split_dir.exists(): - shutil.move(str(split_dir), str(held_split_dir)) + held_bundled_dir = _hold_unused_bundled_dirs(input_dir) try: result = _run_datamodel_codegen(input_dir, OUTPUT_DIR) finally: - if held_split_dir.exists(): - split_dir.parent.mkdir(parents=True, exist_ok=True) - shutil.move(str(held_split_dir), str(split_dir)) + _restore_unused_bundled_dirs(input_dir, held_bundled_dir) _print_codegen_output(result) @@ -438,9 +435,6 @@ def generate_types(input_dir: Path): print(result.stderr, file=sys.stderr) return False - if not _generate_split_bundled_media_buy(input_dir): - return False - return True diff --git a/src/adcp/types/_generated.py b/src/adcp/types/_generated.py index 8d1ad8d87..eb6393051 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-07-01 04:37:49 UTC +Generation date: 2026-07-01 07:44:44 UTC """ # ruff: noqa: E501, I001 @@ -191,7 +191,7 @@ from adcp.types.generated_poc.a2ui.component import A2UiComponent from adcp.types.generated_poc.a2ui.si_catalog import ( Action, - Action7, + Action6, Align, AppHandoff, Apps, @@ -212,7 +212,7 @@ Text, Type, Variant, - Variant5, + Variant4, ) from adcp.types.generated_poc.a2ui.surface import A2UiSurface from adcp.types.generated_poc.a2ui.user_action import A2UiUserAction @@ -241,7 +241,7 @@ from adcp.types.generated_poc.account.report_usage_response import ReportUsageResponse from adcp.types.generated_poc.account.sync_accounts_request import ( Accounts, - Accounts3, + Accounts1, SyncAccountsRequest, ) from adcp.types.generated_poc.account.sync_accounts_response import ( @@ -818,6 +818,21 @@ from adcp.types.generated_poc.core.forecast_range import ForecastRange from adcp.types.generated_poc.core.forecast_vendor_metric_value import ForecastVendorMetricValue from adcp.types.generated_poc.core.format import ( + Assets10, + Assets11, + Assets12, + Assets13, + Assets14, + Assets15, + Assets16, + Assets17, + Assets18, + Assets19, + Assets20, + Assets21, + Assets22, + Assets23, + Assets24, Assets25, Assets26, Assets27, @@ -832,21 +847,6 @@ Assets36, Assets37, Assets38, - Assets39, - Assets40, - Assets41, - Assets42, - Assets43, - Assets44, - Assets45, - Assets46, - Assets47, - Assets48, - Assets49, - Assets50, - Assets51, - Assets52, - Assets53, Assets94, BaseGroupAsset, BaseIndividualAsset, @@ -914,12 +914,12 @@ OptimizationGoal1, OptimizationGoal2, OptimizationGoal3, - Target60, - Target61, - Target62, - Target63, - Target64, - Target65, + Target40, + Target41, + Target42, + Target43, + Target44, + Target45, TargetFrequency, ) from adcp.types.generated_poc.core.outcome_measurement import OutcomeMeasurementDeprecated @@ -1074,7 +1074,7 @@ RenderGuidance, VerificationItem, VerifyAgent, - VerifyAgent1585, + VerifyAgent677, Watermark, ) from adcp.types.generated_poc.core.publisher_property_selector import ( @@ -1252,7 +1252,7 @@ ) from adcp.types.generated_poc.core.signal_definition_enrichment import SignalDefinitionEnrichment from adcp.types.generated_poc.core.signal_filters import SignalFilters -from adcp.types.generated_poc.core.signal_id import SignalId, SignalId57, SignalId58 +from adcp.types.generated_poc.core.signal_id import SignalId, SignalId53, SignalId54 from adcp.types.generated_poc.core.signal_listing import SignalListing from adcp.types.generated_poc.core.signal_modeling_disclosure import SignalModelingDisclosure from adcp.types.generated_poc.core.signal_pricing import ( @@ -1266,9 +1266,9 @@ from adcp.types.generated_poc.core.signal_pricing_option import SignalPricingOption from adcp.types.generated_poc.core.signal_ref import ( SignalRef, - SignalRef115, - SignalRef116, - SignalRef117, + SignalRef106, + SignalRef107, + SignalRef108, ) from adcp.types.generated_poc.core.signal_selection_group_rule import SignalSelectionGroupRule from adcp.types.generated_poc.core.signal_targeting import ( @@ -1647,7 +1647,7 @@ ) from adcp.types.generated_poc.governance.sync_plans_response import ( ResolvedPolicy, - Status214, + Status148, SyncPlansResponse, ) from adcp.types.generated_poc.manifest import Model @@ -1729,7 +1729,7 @@ GetMediaBuysResponse, ) from adcp.types.generated_poc.media_buy.get_products_request import ( - Action3, + Action2, BuyingMode, GetProductsRequest, Refine, @@ -1913,7 +1913,7 @@ GetAdcpCapabilitiesResponse, Governance, Idempotency, - Idempotency1, + Idempotency3, Identity, KeyOrigins, KeywordTargets, @@ -1934,11 +1934,11 @@ SupportedIdentifierType, SupportedOptimizationMetric, SupportedProtocol, - SupportedTarget1, + SupportedTarget3, Surface, Targeting, Transport, - Type9, + Type12, WebhookSigning, WholesaleFeedVersioning, WholesaleFeedWebhooks, @@ -2016,7 +2016,7 @@ DisclosureCommitment, HostReceipt, SiSponsoredContextReceipt, - Status204, + Status146, ) from adcp.types.generated_poc.sponsored_intelligence.si_terminate_session_request import ( SiTerminateSessionRequest, @@ -2148,7 +2148,7 @@ "AccountStatus", "AccountWithAuthorization", "Accounts", - "Accounts3", + "Accounts1", "Accreditation", "AcpHandoff", "AcquireRightsRequest", @@ -2158,8 +2158,8 @@ "AcquireRightsResponse3", "AcquireRightsResponse4", "Action", - "Action3", - "Action7", + "Action2", + "Action6", "ActionNotAllowedDetails", "ActionNotAllowedReason", "ActionResponse", @@ -2246,7 +2246,22 @@ "AssetVariant", "Assets", "Assets1", + "Assets10", + "Assets11", + "Assets12", + "Assets13", + "Assets14", + "Assets15", + "Assets16", + "Assets17", + "Assets18", + "Assets19", "Assets2", + "Assets20", + "Assets21", + "Assets22", + "Assets23", + "Assets24", "Assets25", "Assets26", "Assets27", @@ -2262,22 +2277,7 @@ "Assets36", "Assets37", "Assets38", - "Assets39", "Assets4", - "Assets40", - "Assets41", - "Assets42", - "Assets43", - "Assets44", - "Assets45", - "Assets46", - "Assets47", - "Assets48", - "Assets49", - "Assets50", - "Assets51", - "Assets52", - "Assets53", "Assets94", "AssignedPackage", "Assignment", @@ -2882,7 +2882,7 @@ "IconSize", "IdType", "Idempotency", - "Idempotency1", + "Idempotency3", "Identifier", "Identifiers", "Identity", @@ -3427,15 +3427,15 @@ "SignalFilters", "SignalForecastDimension", "SignalId", - "SignalId57", - "SignalId58", + "SignalId53", + "SignalId54", "SignalListing", "SignalModelingDisclosure", "SignalPricingOption", "SignalRef", - "SignalRef115", - "SignalRef116", - "SignalRef117", + "SignalRef106", + "SignalRef107", + "SignalRef108", "SignalSelectionGroupRule", "SignalSource", "SignalTag", @@ -3481,8 +3481,8 @@ "StandardEnum", "StartTiming", "Status", - "Status204", - "Status214", + "Status146", + "Status148", "StatusFilter", "StatusSummary", "Statuses", @@ -3505,8 +3505,8 @@ "SupportedProtocol", "SupportedTagType", "SupportedTarget", - "SupportedTarget1", "SupportedTarget17", + "SupportedTarget3", "SupportedVersion", "SupportedViewDuration", "Surface", @@ -3557,12 +3557,12 @@ "Talent", "TalentRole", "Target", - "Target60", - "Target61", - "Target62", - "Target63", - "Target64", - "Target65", + "Target40", + "Target41", + "Target42", + "Target43", + "Target44", + "Target45", "TargetFrequency", "Targeting", "TargetingKv", @@ -3621,7 +3621,7 @@ "TruncationSentinel", "TrustedMatch", "Type", - "Type9", + "Type12", "Uid", "UidType", "Unit", @@ -3674,7 +3674,7 @@ "ValueSource", "VariableType", "Variant", - "Variant5", + "Variant4", "VariantAxis", "VariantDimension", "VastAsset", @@ -3716,7 +3716,7 @@ "VerificationLevel", "VerificationStatus", "VerifyAgent", - "VerifyAgent1585", + "VerifyAgent677", "VerifyBrandClaimErrorResponse", "VerifyBrandClaimPayload", "VerifyBrandClaimRequest", diff --git a/src/adcp/types/generated_poc/a2ui/si_catalog.py b/src/adcp/types/generated_poc/a2ui/si_catalog.py index cf0e78e67..feeb5a8c5 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-06-04T19:44:00+00:00 +# timestamp: 2026-07-01T07:44:23+00:00 from __future__ import annotations @@ -56,7 +56,7 @@ class Action(AdCPBaseModel): ] = None -class Variant5(StrEnum): +class Variant4(StrEnum): primary = 'primary' secondary = 'secondary' text = 'text' @@ -65,7 +65,7 @@ class Variant5(StrEnum): class Button(AdCPBaseModel): label: Annotated[bound_value.A2UiBoundValue, Field(description='Button label text')] action: Annotated[Action, Field(description='Action to trigger on click')] - variant: Variant5 | None = Variant5.primary + variant: Variant4 | None = Variant4.primary disabled: bound_value.A2UiBoundValue | None = None @@ -82,7 +82,7 @@ class Image(AdCPBaseModel): height: Annotated[int | None, Field(description='Image height in pixels')] = None -class Action7(AdCPBaseModel): +class Action6(AdCPBaseModel): name: str context: dict[str, bound_value.A2UiBoundValue] | None = None @@ -96,7 +96,7 @@ class Card(AdCPBaseModel): badge: Annotated[ bound_value.A2UiBoundValue | None, Field(description="Badge text (e.g., 'New', 'Sale')") ] = None - action: Annotated[Action7 | None, Field(description='Action to trigger on card click')] = None + action: Annotated[Action6 | None, Field(description='Action to trigger on card click')] = None children: Annotated[list[str] | None, Field(description='Child component IDs')] = None @@ -115,7 +115,7 @@ class ProductCard(AdCPBaseModel): ctaLabel: Annotated[ bound_value.A2UiBoundValue | None, Field(description='CTA button label') ] = None - action: Action7 | None = None + action: Action6 | None = None class Template(AdCPBaseModel): 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 ac0e0da55..fe634bfb5 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-06-18T11:28:05+00:00 +# timestamp: 2026-07-01T07:44:23+00:00 from __future__ import annotations @@ -81,7 +81,7 @@ class Accounts(AdCPBaseModel): ] = None -class Accounts3(AdCPBaseModel): +class Accounts1(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @@ -157,7 +157,7 @@ class SyncAccountsRequest(AdcpVersionEnvelope): ), ] accounts: Annotated[ - list[Accounts | Accounts3], + list[Accounts | Accounts1], Field( description='Per-account sync entries. Each entry uses one of two key shapes: the `account` field (AccountRef) for settings-update mode, or the flat `brand` + `operator` + `billing` trio for provisioning mode.', max_length=1000, 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 68c08c71d..1bbd9bb7a 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-07-01T04:30:58+00:00 +# timestamp: 2026-07-01T07:44:23+00:00 from __future__ import annotations @@ -250,7 +250,7 @@ class Idempotency(AdCPBaseModel): ] = False -class Idempotency3(AdCPBaseModel): +class Idempotency1(AdCPBaseModel): supported: Annotated[ Literal[False], Field(description='Discriminator. False means the seller does not deduplicate retries.'), @@ -288,7 +288,7 @@ class Adcp(AdCPBaseModel): ), ] = None idempotency: Annotated[ - Idempotency | Idempotency3, + Idempotency | Idempotency1, Field( description='Idempotency semantics for mutating requests. Sellers MUST declare whether they honor idempotency_key replay protection so buyers can reason about safe retry behavior. Modeled as a discriminated union on the supported boolean so that code generators produce two named types (IdempotencySupported, IdempotencyUnsupported) with the replay_ttl_seconds invariant enforced at the type level — draft-07 if/then would be dropped by most generators (openapi-typescript, zod-to-json-schema, datamodel-code-generator pre-0.25, quicktype). Clients MUST NOT assume a default — a seller without this declaration is non-compliant and should be treated as unsafe for retry-sensitive operations.' ), @@ -608,7 +608,7 @@ class VendorMetricOptimization(AdCPBaseModel): ] = None -class SupportedTarget3(StrEnum): +class SupportedTarget1(StrEnum): cost_per = 'cost_per' per_ad_spend = 'per_ad_spend' maximize_value = 'maximize_value' @@ -701,7 +701,7 @@ class DiscoveryMode(StrEnum): wholesale = 'wholesale' -class Features2(AdCPBaseModel): +class Features1(AdCPBaseModel): catalog_signals: Annotated[ bool | None, Field( @@ -727,7 +727,7 @@ class Signals(AdCPBaseModel): ), ] = [DiscoveryMode.brief] features: Annotated[ - Features2 | None, Field(description='Optional signals features supported') + Features1 | None, Field(description='Optional signals features supported') ] = None @@ -825,7 +825,7 @@ class Governance(AdCPBaseModel): ] = None -class Type12(StrEnum): +class Type9(StrEnum): mcp = 'mcp' a2a = 'a2a' @@ -834,7 +834,7 @@ class Transport(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) - type: Annotated[Type12, Field(description='Protocol transport type')] + type: Annotated[Type9, Field(description='Protocol transport type')] url: Annotated[AnyUrl, Field(description='Agent endpoint URL for this transport')] @@ -847,7 +847,7 @@ class Endpoint(AdCPBaseModel): ), ] preferred: Annotated[ - Type12 | None, Field(description='Preferred transport when host supports multiple') + Type9 | None, Field(description='Preferred transport when host supports multiple') ] = None @@ -1215,7 +1215,7 @@ class Scope(StrEnum): unknown = 'unknown' -class Status10(StrEnum): +class Status5(StrEnum): connected = 'connected' missing = 'missing' pending = 'pending' @@ -1283,7 +1283,7 @@ class RequiredConnection(AdCPBaseModel): ] = None scope: Annotated[Scope | None, Field(description='Granularity of the downstream grant.')] = None status: Annotated[ - Status10 | None, + Status5 | None, Field( description='Current seller-observed state for this downstream connection when known. Product declarations MAY omit status or use `unknown`; AUTHORIZATION_REQUIRED details SHOULD use `missing`, `expired`, or `revoked` for the connection that blocked the call.' ), @@ -1359,7 +1359,7 @@ class RequiredConnection1(RequiredConnection): pass -class MraidVersion2(StrEnum): +class MraidVersion1(StrEnum): field_2_0 = '2.0' field_3_0 = '3.0' @@ -1442,7 +1442,7 @@ class RequiredConnection5(RequiredConnection): pass -class VastVersion2(StrEnum): +class VastVersion1(StrEnum): field_2_0 = '2.0' field_3_0 = '3.0' field_4_0 = '4.0' @@ -1943,7 +1943,7 @@ class WholesaleFeedVersioning(AdCPBaseModel): ] = None -class Issue7(Issue): +class Issue2(Issue): pass @@ -1976,7 +1976,7 @@ class Error(AdCPBaseModel): ), ] = None issues: Annotated[ - list[Issue7] | None, + list[Issue2] | None, Field( description='Structured list of validation failures. Primary use is `VALIDATION_ERROR`, where multi-field rejections are common and `field` (singular) cannot carry the full pointer map. MAY appear on other error codes that reject multiple fields at once. When `issues` is present, sellers MUST also populate `field` from `issues[0]` for backward compatibility with pre-3.1 consumers that read `field` only — translating the RFC 6901 `pointer` format to the JSONPath-lite format `field` uses (e.g., `/packages/0/targeting` → `packages[0].targeting`). MUST (not SHOULD) so consumers reading `field` get deterministic behavior across sellers — the cost is one line of dual-write per seller; the cost of SHOULD is a long tail of seller-A-vs-seller-B inconsistency. Future major versions will deprecate `field` in favor of `issues[].pointer`.' ), @@ -2007,7 +2007,7 @@ class Error(AdCPBaseModel): ] = None -class EventType2(StrEnum): +class EventType1(StrEnum): product_created = 'product.created' product_updated = 'product.updated' product_priced = 'product.priced' @@ -2030,7 +2030,7 @@ class WholesaleFeedWebhooks(AdCPBaseModel): ), ] event_types: Annotated[ - list[EventType2] | None, + list[EventType1] | None, Field( description='Wholesale feed webhook event types this agent can emit. Sales agents emit product.* events. Signals agents emit signal.* events. Agents that are both can emit both event families. Agents listing product.* event types MUST declare and support get_products with media_buy.buying_modes including wholesale. Agents listing signal.* event types MUST declare and support get_signals with signals.discovery_modes including wholesale. wholesale_feed.bulk_change tells consumers to repair by re-reading the affected wholesale feed via get_products and/or get_signals; agents listing it MUST have at least one of those wholesale repair paths and MUST only emit bulk-change payloads for affected_entity_type values backed by a declared repair path.', min_length=1, @@ -2310,7 +2310,7 @@ class ConversionTracking(AdCPBaseModel): ), ] = None supported_targets: Annotated[ - list[SupportedTarget3] | None, + list[SupportedTarget1] | None, Field( description='Event-goal target kinds this seller can compute against. Buyers should only submit event-kind optimization goals whose target.kind is listed here — sellers MUST reject goals with unlisted target kinds. When omitted, only target-less event goals (maximize conversion count within budget) are guaranteed; sellers MAY accept specific target kinds but buyers should not rely on it. Named to parallel `metric_optimization.supported_targets` at the product level — same concept (which target kinds are supported), one at seller-capability granularity and one at product granularity.', min_length=1, @@ -2989,7 +2989,7 @@ class Params2(AdCPBaseModel): bool | None, Field(description='Whether MRAID compatibility is required (mobile in-app).') ] = None mraid_version: Annotated[ - MraidVersion2 | None, + MraidVersion1 | None, Field(description='Required MRAID version when mraid_required is true.'), ] = None om_sdk_required: Annotated[ @@ -3879,7 +3879,7 @@ class Params6(AdCPBaseModel): aspect_ratio: Annotated[ str | None, Field(pattern='^[0-9]+(\\.[0-9]+)?:[0-9]+(\\.[0-9]+)?$') ] = None - vast_version: Annotated[VastVersion2 | None, Field(description='Required VAST version.')] = None + vast_version: Annotated[VastVersion1 | None, Field(description='Required VAST version.')] = None vpaid_enabled: Annotated[ bool | None, Field( diff --git a/src/adcp/types/generated_poc/core/format.py b/src/adcp/types/generated_poc/core/format.py index 906f324d7..0f2f8697f 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-06-07T23:07:52+00:00 +# timestamp: 2026-07-01T07:44:23+00:00 from __future__ import annotations @@ -267,183 +267,183 @@ class Assets(BaseIndividualAsset): requirements: image_asset_requirements.ImageAssetRequirements | None = None -class Assets25(BaseIndividualAsset): +class Assets10(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['video'] = 'video' requirements: video_asset_requirements.VideoAssetRequirements | None = None -class Assets26(BaseIndividualAsset): +class Assets11(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['audio'] = 'audio' requirements: audio_asset_requirements.AudioAssetRequirements | None = None -class Assets27(BaseIndividualAsset): +class Assets12(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['text'] = 'text' requirements: text_asset_requirements.TextAssetRequirements | None = None -class Assets28(BaseIndividualAsset): +class Assets13(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['markdown'] = 'markdown' requirements: markdown_asset_requirements.MarkdownAssetRequirements | None = None -class Assets29(BaseIndividualAsset): +class Assets14(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['html'] = 'html' requirements: html_asset_requirements.HtmlAssetRequirements | None = None -class Assets30(BaseIndividualAsset): +class Assets15(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['css'] = 'css' requirements: css_asset_requirements.CssAssetRequirements | None = None -class Assets31(BaseIndividualAsset): +class Assets16(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['javascript'] = 'javascript' requirements: javascript_asset_requirements.JavascriptAssetRequirements | None = None -class Assets32(BaseIndividualAsset): +class Assets17(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['zip'] = 'zip' -class Assets33(BaseIndividualAsset): +class Assets18(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['vast'] = 'vast' requirements: vast_asset_requirements.VastAssetRequirements | None = None -class Assets34(BaseIndividualAsset): +class Assets19(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['daast'] = 'daast' requirements: daast_asset_requirements.DaastAssetRequirements | None = None -class Assets35(BaseIndividualAsset): +class Assets20(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['url'] = 'url' requirements: url_asset_requirements.UrlAssetRequirements | None = None -class Assets36(BaseIndividualAsset): +class Assets21(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['webhook'] = 'webhook' requirements: webhook_asset_requirements.WebhookAssetRequirements | None = None -class Assets37(BaseIndividualAsset): +class Assets22(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['brief'] = 'brief' -class Assets38(BaseIndividualAsset): +class Assets23(BaseIndividualAsset): item_type: Literal['individual'] = 'individual' asset_type: Literal['catalog'] = 'catalog' requirements: catalog_requirements.CatalogRequirements | None = None -class Assets41(BaseGroupAsset): +class Assets26(BaseGroupAsset): asset_type: Literal['image'] = 'image' requirements: image_asset_requirements.ImageAssetRequirements | None = None -class Assets42(BaseGroupAsset): +class Assets27(BaseGroupAsset): asset_type: Literal['video'] = 'video' requirements: video_asset_requirements.VideoAssetRequirements | None = None -class Assets43(BaseGroupAsset): +class Assets28(BaseGroupAsset): asset_type: Literal['audio'] = 'audio' requirements: audio_asset_requirements.AudioAssetRequirements | None = None -class Assets44(BaseGroupAsset): +class Assets29(BaseGroupAsset): asset_type: Literal['text'] = 'text' requirements: text_asset_requirements.TextAssetRequirements | None = None -class Assets45(BaseGroupAsset): +class Assets30(BaseGroupAsset): asset_type: Literal['markdown'] = 'markdown' requirements: markdown_asset_requirements.MarkdownAssetRequirements | None = None -class Assets46(BaseGroupAsset): +class Assets31(BaseGroupAsset): asset_type: Literal['html'] = 'html' requirements: html_asset_requirements.HtmlAssetRequirements | None = None -class Assets47(BaseGroupAsset): +class Assets32(BaseGroupAsset): asset_type: Literal['css'] = 'css' requirements: css_asset_requirements.CssAssetRequirements | None = None -class Assets48(BaseGroupAsset): +class Assets33(BaseGroupAsset): asset_type: Literal['javascript'] = 'javascript' requirements: javascript_asset_requirements.JavascriptAssetRequirements | None = None -class Assets49(BaseGroupAsset): +class Assets34(BaseGroupAsset): asset_type: Literal['zip'] = 'zip' -class Assets50(BaseGroupAsset): +class Assets35(BaseGroupAsset): asset_type: Literal['vast'] = 'vast' requirements: vast_asset_requirements.VastAssetRequirements | None = None -class Assets51(BaseGroupAsset): +class Assets36(BaseGroupAsset): asset_type: Literal['daast'] = 'daast' requirements: daast_asset_requirements.DaastAssetRequirements | None = None -class Assets52(BaseGroupAsset): +class Assets37(BaseGroupAsset): asset_type: Literal['url'] = 'url' requirements: url_asset_requirements.UrlAssetRequirements | None = None -class Assets53(BaseGroupAsset): +class Assets38(BaseGroupAsset): asset_type: Literal['webhook'] = 'webhook' requirements: webhook_asset_requirements.WebhookAssetRequirements | None = None -class Assets40( +class Assets25( RootModel[ - Assets41 - | Assets42 - | Assets43 - | Assets44 - | Assets45 - | Assets46 - | Assets47 - | Assets48 - | Assets49 - | Assets50 - | Assets51 - | Assets52 - | Assets53 + Assets26 + | Assets27 + | Assets28 + | Assets29 + | Assets30 + | Assets31 + | Assets32 + | Assets33 + | Assets34 + | Assets35 + | Assets36 + | Assets37 + | Assets38 ] ): root: Annotated[ - Assets41 - | Assets42 - | Assets43 - | Assets44 - | Assets45 - | Assets46 - | Assets47 - | Assets48 - | Assets49 - | Assets50 - | Assets51 - | Assets52 - | Assets53, + Assets26 + | Assets27 + | Assets28 + | Assets29 + | Assets30 + | Assets31 + | Assets32 + | Assets33 + | Assets34 + | Assets35 + | Assets36 + | Assets37 + | Assets38, Field(discriminator='asset_type'), ] def __getattr__(self, name: str) -> Any: @@ -452,7 +452,7 @@ def __getattr__(self, name: str) -> Any: raise AttributeError(name) return getattr(self.root, name) -class Assets39(AdCPBaseModel): +class Assets24(AdCPBaseModel): item_type: Annotated[ Literal['repeatable_group'], Field(description='Discriminator indicating this is a repeatable asset group'), @@ -481,7 +481,7 @@ class Assets39(AdCPBaseModel): ), ] = SelectionMode.sequential assets: Annotated[ - list[Assets40], Field(description='Assets within each repetition of this group') + list[Assets25], Field(description='Assets within each repetition of this group') ] @@ -524,21 +524,21 @@ class Format(AdCPBaseModel): assets: Annotated[ list[ Assets - | Assets25 - | Assets26 - | Assets27 - | Assets28 - | Assets29 - | Assets30 - | Assets31 - | Assets32 - | Assets33 - | Assets34 - | Assets35 - | Assets36 - | Assets37 - | Assets38 - | Assets39 + | Assets10 + | Assets11 + | Assets12 + | Assets13 + | Assets14 + | Assets15 + | Assets16 + | Assets17 + | Assets18 + | Assets19 + | Assets20 + | Assets21 + | Assets22 + | Assets23 + | Assets24 ] | None, Field( @@ -632,4 +632,4 @@ class Format(AdCPBaseModel): # Backward compatibility for the pre-beta3 generated repeatable group name. -Assets94 = Assets39 +Assets94 = Assets24 diff --git a/src/adcp/types/generated_poc/core/optimization_goal.py b/src/adcp/types/generated_poc/core/optimization_goal.py index 53edae1ee..f974c1000 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-06-12T11:05:47+00:00 +# timestamp: 2026-07-01T07:44:23+00:00 from __future__ import annotations @@ -66,7 +66,7 @@ class Target(AdCPBaseModel): ] -class Target60(AdCPBaseModel): +class Target40(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @@ -117,7 +117,7 @@ class EventSource(AdCPBaseModel): ] = 1 -class Target61(AdCPBaseModel): +class Target41(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @@ -125,7 +125,7 @@ class Target61(AdCPBaseModel): value: Annotated[float, Field(description='Target cost per event in the buy currency', gt=0.0)] -class Target62(AdCPBaseModel): +class Target42(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @@ -136,14 +136,14 @@ class Target62(AdCPBaseModel): ] -class Target63(AdCPBaseModel): +class Target43(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) kind: Literal['maximize_value'] = 'maximize_value' -class Target64(AdCPBaseModel): +class Target44(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @@ -157,7 +157,7 @@ class Target64(AdCPBaseModel): ] -class Target65(AdCPBaseModel): +class Target45(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @@ -202,7 +202,7 @@ class OptimizationGoal1(AdCPBaseModel): ), ] = None target: Annotated[ - Target | Target60 | None, + Target | Target40 | None, Field( description='Target for this metric. When omitted, the seller optimizes for maximum metric volume within budget.', discriminator='kind', @@ -230,7 +230,7 @@ class OptimizationGoal2(AdCPBaseModel): ), ] target: Annotated[ - Target61 | Target62 | Target63 | None, + Target41 | Target42 | Target43 | None, Field( description='Target cost or return for this event goal. When omitted, the seller optimizes for maximum conversion count within budget — regardless of whether value_field is present on event sources. The presence of value_field alone does not change the optimization objective; it only makes value available for reporting. An explicit target of maximize_value or per_ad_spend is required to steer toward value.', discriminator='kind', @@ -269,7 +269,7 @@ class OptimizationGoal3(AdCPBaseModel): ), ] target: Annotated[ - Target64 | Target65 | None, + Target44 | Target45 | None, Field( description="Target for this vendor metric. When omitted, the seller optimizes for maximum metric volume / score within budget. `cost_per` and `threshold_rate` semantics mirror the same target kinds on the `metric` kind — units are vendor-defined and depend on the vendor's `measurement.metrics[]` declaration for this `metric_id`.", discriminator='kind', diff --git a/src/adcp/types/generated_poc/core/provenance.py b/src/adcp/types/generated_poc/core/provenance.py index 0ecf01899..d7ddd9d07 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-06-05T16:54:33+00:00 +# timestamp: 2026-07-01T07:44:23+00:00 from __future__ import annotations @@ -130,7 +130,7 @@ class EmbeddedProvenanceItem(AdCPBaseModel): ] = None -class VerifyAgent1585(AdCPBaseModel): +class VerifyAgent677(AdCPBaseModel): model_config = ConfigDict( extra='forbid', ) @@ -269,7 +269,7 @@ class Watermark(AdCPBaseModel): ), ] verify_agent: Annotated[ - VerifyAgent1585 | None, + VerifyAgent677 | None, Field( description="Buyer's representation that this watermark can be detected by a governance agent on the seller's `creative_policy.accepted_verifiers` list. The `agent_url` MUST match (canonicalized) one of the seller's published `accepted_verifiers[].agent_url` entries; sellers reject `sync_creatives` submissions whose `verify_agent.agent_url` is off-list with `PROVENANCE_VERIFIER_NOT_ACCEPTED`. This is buyer-supplied evidence, not buyer-driven routing — the seller is the verifier-of-record and the seller controls which agent it actually calls (the seller MAY use a different on-list agent if it determines this is more appropriate; the seller does not call buyer-asserted endpoints outside its allowlist)." ), diff --git a/src/adcp/types/generated_poc/core/signal_id.py b/src/adcp/types/generated_poc/core/signal_id.py index d7596c0ca..5df4c24b7 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-06-05T16:54:33+00:00 +# timestamp: 2026-07-01T07:44:23+00:00 from __future__ import annotations @@ -10,7 +10,7 @@ from pydantic import AnyUrl, ConfigDict, Field, RootModel -class SignalId57(AdCPBaseModel): +class SignalId53(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @@ -36,7 +36,7 @@ class SignalId57(AdCPBaseModel): ] -class SignalId58(AdCPBaseModel): +class SignalId54(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @@ -61,9 +61,9 @@ class SignalId58(AdCPBaseModel): ] -class SignalId(RootModel[SignalId57 | SignalId58]): +class SignalId(RootModel[SignalId53 | SignalId54]): root: Annotated[ - SignalId57 | SignalId58, + SignalId53 | SignalId54, Field( description="DEPRECATED. Use SignalRef for new discovery, activation, and media-buy signal identity surfaces. Legacy universal signal identifier used by older Signals Protocol clients. Uses 'source' as discriminator: 'catalog' for signals from a data provider's published catalog (verifiable), or 'agent' for signals native to a signal source identified by agent_url.", discriminator='source', diff --git a/src/adcp/types/generated_poc/core/signal_ref.py b/src/adcp/types/generated_poc/core/signal_ref.py index 905bd09e7..75897d116 100644 --- a/src/adcp/types/generated_poc/core/signal_ref.py +++ b/src/adcp/types/generated_poc/core/signal_ref.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: core/signal_ref.json -# timestamp: 2026-06-04T19:44:00+00:00 +# timestamp: 2026-07-01T07:44:23+00:00 from __future__ import annotations @@ -10,7 +10,7 @@ from pydantic import AnyUrl, ConfigDict, Field, RootModel -class SignalRef115(AdCPBaseModel): +class SignalRef106(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @@ -29,7 +29,7 @@ class SignalRef115(AdCPBaseModel): ] -class SignalRef116(AdCPBaseModel): +class SignalRef107(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @@ -55,7 +55,7 @@ class SignalRef116(AdCPBaseModel): ] -class SignalRef117(AdCPBaseModel): +class SignalRef108(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) @@ -77,9 +77,9 @@ class SignalRef117(AdCPBaseModel): ] -class SignalRef(RootModel[SignalRef115 | SignalRef116 | SignalRef117]): +class SignalRef(RootModel[SignalRef106 | SignalRef107 | SignalRef108]): root: Annotated[ - SignalRef115 | SignalRef116 | SignalRef117, + SignalRef106 | SignalRef107 | SignalRef108, Field( description="Reference to a named signal definition. Uses scope as discriminator: 'data_provider' for a signal resolved through published adagents.json signals[], 'signal_source' for a source-native signal resolved through the issuing signal source, or 'product' for a product-local signal option. Scope is the resolution path, not provenance; authoritative enrichment lives on the seller, signal source, or data-provider signal definition, not on this reference.", discriminator='scope', 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 8343dc7ea..38fae139e 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-06-18T11:28:05+00:00 +# timestamp: 2026-07-01T07:44:23+00:00 from __future__ import annotations @@ -22,7 +22,7 @@ class Status(StrEnum): error = 'error' -class Status214(StrEnum): +class Status148(StrEnum): active = 'active' inactive = 'inactive' @@ -33,7 +33,7 @@ class Category(AdCPBaseModel): ) category_id: Annotated[str, Field(description='Validation category identifier.')] status: Annotated[ - Status214, Field(description='Whether this category is active for this plan.') + Status148, Field(description='Whether this category is active for this plan.') ] 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 c01f24ed3..bad570557 100644 --- a/src/adcp/types/generated_poc/media_buy/get_products_request.py +++ b/src/adcp/types/generated_poc/media_buy/get_products_request.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: media_buy/get_products_request.json -# timestamp: 2026-07-01T04:30:58+00:00 +# timestamp: 2026-07-01T07:44:23+00:00 from __future__ import annotations @@ -75,7 +75,7 @@ class Refine2(AdCPBaseModel): ] = None -class Action3(StrEnum): +class Action2(StrEnum): include = 'include' omit = 'omit' finalize = 'finalize' @@ -92,11 +92,11 @@ class Refine3(AdCPBaseModel): str, Field(description='Proposal ID from a previous get_products response.', min_length=1) ] action: Annotated[ - Action3 | None, + Action2 | None, Field( 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'.\n\nFinalize is exclusive within the parent `refine[]` array: see the array-level description for the finalize-exclusivity rule (mixing finalize with non-finalize entries is rejected) and multi-finalize atomicity contract." ), - ] = Action3.include + ] = Action2.include ask: Annotated[ str | None, Field( 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 53c28c755..b0ce223f8 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-07-01T04:30:58+00:00 +# timestamp: 2026-07-01T07:44:23+00:00 from __future__ import annotations @@ -83,7 +83,7 @@ class Idempotency(AdCPBaseModel): ] = False -class Idempotency1(AdCPBaseModel): +class Idempotency3(AdCPBaseModel): supported: Annotated[ Literal[False], Field(description='Discriminator. False means the seller does not deduplicate retries.'), @@ -121,7 +121,7 @@ class Adcp(AdCPBaseModel): ), ] = None idempotency: Annotated[ - Idempotency | Idempotency1, + Idempotency | Idempotency3, Field( description='Idempotency semantics for mutating requests. Sellers MUST declare whether they honor idempotency_key replay protection so buyers can reason about safe retry behavior. Modeled as a discriminated union on the supported boolean so that code generators produce two named types (IdempotencySupported, IdempotencyUnsupported) with the replay_ttl_seconds invariant enforced at the type level — draft-07 if/then would be dropped by most generators (openapi-typescript, zod-to-json-schema, datamodel-code-generator pre-0.25, quicktype). Clients MUST NOT assume a default — a seller without this declaration is non-compliant and should be treated as unsafe for retry-sensitive operations.' ), @@ -307,7 +307,7 @@ class VendorMetricOptimization(AdCPBaseModel): ] = None -class SupportedTarget1(StrEnum): +class SupportedTarget3(StrEnum): cost_per = 'cost_per' per_ad_spend = 'per_ad_spend' maximize_value = 'maximize_value' @@ -533,7 +533,7 @@ class Governance(AdCPBaseModel): ] = None -class Type9(StrEnum): +class Type12(StrEnum): mcp = 'mcp' a2a = 'a2a' @@ -542,7 +542,7 @@ class Transport(AdCPBaseModel): model_config = ConfigDict( extra='allow', ) - type: Annotated[Type9, Field(description='Protocol transport type')] + type: Annotated[Type12, Field(description='Protocol transport type')] url: Annotated[AnyUrl, Field(description='Agent endpoint URL for this transport')] @@ -555,7 +555,7 @@ class Endpoint(AdCPBaseModel): ), ] preferred: Annotated[ - Type9 | None, Field(description='Preferred transport when host supports multiple') + Type12 | None, Field(description='Preferred transport when host supports multiple') ] = None @@ -1093,7 +1093,7 @@ class ConversionTracking(AdCPBaseModel): ), ] = None supported_targets: Annotated[ - list[SupportedTarget1] | None, + list[SupportedTarget3] | None, Field( description='Event-goal target kinds this seller can compute against. Buyers should only submit event-kind optimization goals whose target.kind is listed here — sellers MUST reject goals with unlisted target kinds. When omitted, only target-less event goals (maximize conversion count within budget) are guaranteed; sellers MAY accept specific target kinds but buyers should not rely on it. Named to parallel `metric_optimization.supported_targets` at the product level — same concept (which target kinds are supported), one at seller-capability granularity and one at product granularity.', min_length=1, diff --git a/src/adcp/types/generated_poc/sponsored_intelligence/si_sponsored_context_receipt.py b/src/adcp/types/generated_poc/sponsored_intelligence/si_sponsored_context_receipt.py index ac8cdfef4..45887c23b 100644 --- a/src/adcp/types/generated_poc/sponsored_intelligence/si_sponsored_context_receipt.py +++ b/src/adcp/types/generated_poc/sponsored_intelligence/si_sponsored_context_receipt.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: sponsored_intelligence/si_sponsored_context_receipt.json -# timestamp: 2026-06-18T11:28:05+00:00 +# timestamp: 2026-07-01T07:44:23+00:00 from __future__ import annotations @@ -19,7 +19,7 @@ class Status(StrEnum): rejected = 'rejected' -class Status204(StrEnum): +class Status146(StrEnum): accepted = 'accepted' not_required = 'not_required' @@ -29,7 +29,7 @@ class DisclosureCommitment(AdCPBaseModel): extra='allow', ) status: Annotated[ - Status204, + Status146, Field( description="Host commitment status for the disclosure obligation. Use accepted when the declaration requires disclosure and the host will satisfy it; use not_required only when the declaration's disclosure_obligation.required is false. A host that will not satisfy a required disclosure rejects the sponsored context." ), From a2c73e5d0e709dcc81f6336edfe1fb0814110c86 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Wed, 1 Jul 2026 08:53:33 +0100 Subject: [PATCH 4/4] test(capabilities): avoid generated suffix pin --- tests/test_decisioning_capabilities_submodule.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_decisioning_capabilities_submodule.py b/tests/test_decisioning_capabilities_submodule.py index 2d4a3c2b6..e47e14026 100644 --- a/tests/test_decisioning_capabilities_submodule.py +++ b/tests/test_decisioning_capabilities_submodule.py @@ -36,7 +36,8 @@ def test_wire_spec_names_resolve_in_submodule() -> None: assert Adcp.__name__ == "Adcp" assert Targeting.__name__ == "Targeting" assert IdempotencySupported.__name__ == "Idempotency" # the supported variant - assert IdempotencyUnsupported.__name__ == "Idempotency3" # the unsupported variant + assert IdempotencyUnsupported is not IdempotencySupported + assert IdempotencyUnsupported.__name__.startswith("Idempotency") # the unsupported variant def test_capability_sub_models_construct() -> None: