diff --git a/.changeset/pre.json b/.changeset/pre.json index 8ac21682d..bbe02f6b1 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -6,9 +6,14 @@ }, "changesets": [ "a2ui-mcp-apps-support", + "aao-brand-db-managed", "account-id-delivery", "account-linking-design", + "account-management-docs-location", + "account-ref-setup-account", "accounts-and-agents", + "accounts-task-reference-pages", + "accounts-to-admin", "add-channel-fields", "add-cpa-pricing", "add-creative-protocol", @@ -17,61 +22,108 @@ "add-update-meeting-tool", "add-v3-beta-docs", "addie-code-version", + "addie-escalation-confirm-create-wg", + "addie-past-due-invoices", + "addie-prebid-improvements", + "addie-property-registry-context", + "addie-public-channel-guardrails", + "addie-testing-suite", "addie-thread-restraint", + "addie-thread-review", + "afraid-ducks-teach", "afraid-times-cover", "alert-dedupe-url", "all-books-dance", + "app-catalog-type", "assets-discovery", "attribution-window", + "better-hounds-bet", + "blue-bees-learn", "bold-items-refuse", "brand-builder-ux", + "brand-identity-ghost-text", "brand-manifest-tone-logos", "brand-protocol", + "brand-registry-lookup", + "brand-registry-primary", + "brand-unification-v3", + "brave-houses-happen", "breezy-emus-knock", "calm-deserts-share", + "campaign-ref", + "catalog-binding-discriminator", + "catalog-item-macros", + "catalog-typed-assets", "chilly-apes-sneeze", + "chubby-suns-worry", + "clarify-push-notifications", "clean-papayas-wink", "commerce-attribution-metrics", "committee-leader-tools", "content-standards-fixes", "content-standards-protocol", "cool-maps-sniff", + "cool-papers-double", + "creative-format-capabilities", + "creative-governance", + "creative-manifest-multi-catalog", "creative-performance", "crisp-goats-sink", "cuddly-mirrors-type", "cuddly-worms-wear", "curvy-kiwis-clap", "cyan-rings-repeat", + "date-range-exclusive-docs", + "deep-facts-say", "delivery-forecasting", "deprecate-format-category", "dirty-hoops-eat", "dirty-parts-slide", "doc-naming-cleanup", + "doc-save-endpoints", "docs-auto-merge", "document-github-bundled-schemas", "early-grapes-find", "easy-bears-hear", "eight-clouds-start", + "eight-lilies-sleep", "eighty-dingos-lay", + "eleven-experts-hang", "eleven-icons-learn", "eleven-insects-post", "eleven-ties-exist", "empty-ducks-press", + "empty-gifts-go", + "event-visibility-tiers", "fair-feet-shop", + "fair-seals-obey", + "famous-adults-cross", + "famous-coins-follow", "famous-donuts-float", "few-dots-build", "few-regions-rule", "few-rivers-travel", "fine-loops-design", + "fine-moose-dig", "five-trains-feel", "fix-account-index", + "fix-addie-brand-tools", + "fix-addie-issues", "fix-admin-role-update", "fix-auto-add-members", "fix-auto-add-pagination", + "fix-brand-identity-bugs", + "fix-brand-registry-search", "fix-broken-links", "fix-broken-logo", + "fix-build-creative-catalog-examples", "fix-calendar-timezone", + "fix-community-brand-display", + "fix-dist-versioned-links", "fix-hot-prospect-links", + "fix-mcp-cors-on-401", + "fix-mcp-oauth-base-url", + "fix-mcp-oauth-redirect", "fix-meeting-id-lookup", "fix-meeting-z-suffix", "fix-meetings-section-display", @@ -79,22 +131,39 @@ "fix-member-metrics", "fix-oauth-response-parsing", "fix-oauth-urls", - "fix-open-invoice-display", + "fix-org-merge-roles-and-personal-domains", "fix-owner-role-update", + "fix-registry-agent-type-mcp-url", + "fix-schema-version-sorting", + "fix-sk-api-key-auth", + "fix-sync-audiences-schema-links", + "fix-task-reminder-completion", + "fix-utf8-encoding", + "fix-v3-overview-heading", "fix-zoom-meeting-timezone", "floppy-cars-flash", "format-reported-metrics", "frank-donkeys-dress", + "frank-roses-stop", "frank-teeth-jam", + "free-cats-wait", + "fresh-tools-relate", + "fruity-kids-relate", + "full-mirrors-visit", + "funky-dingos-sing", + "gentle-cycles-fail", "geo-exclusion-targeting", "get-capabilities-task", + "get-media-buys-task", "gold-chefs-wear", "gold-items-walk", "good-jars-post", + "goofy-owls-kiss", "great-buckets-smell", "green-rice-relate", "grumpy-things-shop", "happy-singers-cry", + "heavy-signs-rescue", "hip-numbers-train", "honest-bees-glow", "honest-maps-decide", @@ -104,40 +173,61 @@ "itchy-gifts-go", "itchy-ravens-feel", "kind-insects-act", + "late-candies-slide", + "legal-falcons-cheer", "legal-islands-kick", "lemon-bats-stop", "lemon-ideas-greet", + "light-mangos-share", "light-rats-fix", "light-tables-stare", + "little-islands-fetch", "little-kings-grow", "little-trams-hear", + "long-boats-nail", "long-hotels-yell", "long-melons-rush", "loose-brooms-smell", "loud-bushes-train", + "loud-vans-pump", "lucky-guests-find", + "lusha-prospect-lookup", "major-eels-beam", + "manage-tier", + "many-ducks-speak", "media-channel-taxonomy", + "member-dashboard-nav", + "member-engagement", + "member-referral-codes", "members-page-refactor", "membership-tier-selection", "metal-cows-tickle", "metal-dryers-teach", + "metal-flies-dance", "metal-hats-agree", "moltbook-engagement-updates", "moody-beers-love", "moody-books-argue", + "moody-geckos-kneel", "neat-cats-hang", + "neat-eggs-speak", "neat-groups-give", "nice-kings-add", "nice-pants-hope", + "nine-candles-wait", "nine-keys-stop", "nine-laws-marry", "ninety-balloons-wear", + "offering-asset-group", "old-aliens-live", "old-canyons-serve", "olive-rivers-cut", "openai-product-feed", "optable-publish-fix", + "optimization-goal-capability-gaps", + "optimization-goals-array", + "overlays-for-asset-chrome", + "petite-balloons-tie", "plain-loops-listen", "plenty-pears-own", "polite-paws-heal", @@ -146,33 +236,53 @@ "preview-format-id-optional", "price-guidance-shared-schema", "pricing-option-semantics", + "pricing-options-vendor-protocols", "product-selectors", + "promoted-offerings-required-fields", + "property-check-registry", "property-governance-protocol", "property-targeting-allowed", "protocol-specifications", + "proud-pillows-like", + "proxy-brandfetch-logos", "public-banks-remain", "public-falcons-like", + "public-trees-fail", + "purple-apples-punch", "purple-sloths-march", "ready-tools-punch", "reduce-log-noise", "remove-data-models-docs", + "remove-estimated-exposures", + "remove-orgs-admin-page", + "remove-proposal-refinement", "remove-v3-deprecated", "replace-brand-examples", "revenue-tier-ui", "rich-toes-grow", "salty-deer-end", + "salty-experts-tap", + "sandbox-mode", "schema-ref-dedup", "session-id-fallback", "seven-views-knock", + "shaggy-sides-buy", "shaky-areas-go", "sharp-rice-smile", "shiny-donuts-guess", "shiny-dots-act", + "shiny-nails-battle", + "short-icons-itch", + "short-towns-chew", + "show-brand-json-url", "shy-kings-crash", "shy-rivers-hug", + "shy-suns-fix", "signal-catalog", + "signals-catalog-nav", "silent-adults-nail", "silent-lilies-check", + "silent-wasps-lay", "silly-animals-lead", "silly-paws-lick", "simplify-filters", @@ -182,47 +292,80 @@ "slimy-paths-beam", "slow-owls-pick", "smart-pants-admire", + "smart-webs-boil", "smooth-falcons-learn", "smooth-swans-reply", "social-clubs-wait", + "social-ends-attack", "solid-rooms-scream", + "sour-birds-mate", + "sour-candies-serve", + "sour-cars-sneeze", + "sparkly-hands-check", "sparkly-plums-boil", "sparkly-wings-slide", "spicy-terms-hope", + "spotty-lizards-write", + "spotty-nights-happen", "stale-carpets-warn", "standardize-pagination", + "strong-baboons-read", "strong-wings-cough", "sunny-cars-pick", "sunny-coats-punch", + "swiss-austrian-postal-targeting", + "sync-audiences", "tall-rats-clean", "tame-lions-sort", "tangy-otters-hear", "targeting-restrictions", "tasty-llamas-fail", "ten-roses-marry", + "tender-chicken-crash", + "tender-jokes-design", "tender-pens-stare", + "tender-rabbits-move", "tender-trees-cut", + "tender-wolves-type", + "thirty-spies-play", + "three-lemons-fix", + "three-streets-warn", "timezone-meeting-fix", + "tiny-eyes-marry", "tiny-groups-share", + "tired-balloons-tickle", "tired-tips-grab", "tough-bottles-roll", "tough-eels-dance", "tricky-ideas-try", "true-buttons-fall", "twelve-candles-admire", + "twelve-forks-tap", "twelve-hounds-stand", "twenty-deserts-spend", "typed-asset-requirements", "universal-macros-enum", + "update-media-buy-state-preconditions", + "upset-grapes-behave", "upset-sheep-drive", + "vast-points-shave", "video-asset-constraints", + "wacky-ants-help", + "warm-canyons-cry", + "warm-things-reply", + "web-chat-tool-parity", "wet-weeks-throw", "whole-sides-join", + "wholesale-buying-mode", + "wicked-insects-scream", + "wicked-sites-taste", "wide-papers-see", "wide-regions-tan", + "wild-poems-film", "wild-trains-vanish", "yellow-baboons-arrive", "yellow-deer-brush", + "yellow-lizards-mix", "yellow-phones-walk" ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d1174a1e..0d580dbf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,267 @@ # Changelog +## 3.0.0-beta.4 + +### Major Changes + +- 892da1d: Delete brand-manifest.json. The brand object in brand.json is now the single + canonical brand definition. Task schemas reference brands by domain + brand_id + instead of passing inline manifests. Brand data is always resolved from + brand.json or the registry. +- 5b8feea: **BREAKING**: Rename `catalog` to `catalogs` (array) on creative manifest. Formats can declare multiple catalog_requirements (e.g., product + inventory + store); the manifest now supports multiple catalogs to match. Each catalog's `type` maps to the corresponding catalog_requirements entry. +- 7cf7476: Remove `estimated_exposures` from Product, replace with optional `forecast` + + - Remove the unitless `estimated_exposures` integer field from the Product schema + - Add optional `forecast` field using the existing `DeliveryForecast` type, giving buyers structured delivery estimates with time periods, metric ranges, and methodology context during product discovery + +- 811bd0e: Remove `proposal_id` from get_products request schema + + Proposal refinement now uses protocol-level session continuity (`context_id` in MCP, `contextId` in A2A) instead of a task-level parameter. This makes refinement consistent across get_products, get_signals, and build_creative. Proposal execution via create_media_buy is unchanged. + +- 4c33b99: Add required `buying_mode` discriminator to `get_products` request for explicit wholesale vs curated buying intent. + + Buyers with their own audience stacks (DMPs, CDPs, AXE integrations) can now set `buying_mode: "wholesale"` to declare they want raw inventory without publisher curation. Buyers using curated discovery set `buying_mode: "brief"` and include `brief`. This removes ambiguity from legacy requests that omitted `buying_mode`. + + When `buying_mode` is `"wholesale"`: + + - Publisher returns products supporting buyer-directed targeting + - No AI curation or personalization is applied + - No proposals are returned + - `brief` must not be provided (mutually exclusive) + +### Minor Changes + +- f6336af: Serve AgenticAdvertising.org brand.json from hosted_brands database so it can be managed via Addie tools. Seed initial brand data including structured tone format with voice and attributes. +- a9e118d: Introduce Accounts Protocol documentation as a named cross-protocol section covering commercial infrastructure: `sync_accounts`, `list_accounts`, and `report_usage`. Includes Accounts Protocol overview connecting brand registry, account establishment, and settlement into a transaction lifecycle. Moves account management tasks from Media Buy Protocol to the new Accounts Protocol section. +- 142bcd5: Replace account_id with account reference, restructure account model. + + - Add `account-ref.json`: union type accepting `{ account_id }` or `{ brand, operator }` + - Use `brand-ref.json` (domain + brand_id) instead of flat house + brand_id in account schemas + - Make `operator` required everywhere (brand sets operator to its own domain when operating its own seat) + - Add `account_resolution` capability (string: `explicit_account_id` or `implicit_from_sync`) + - Simplify billing to `operator` or `agent` only (brand-as-operator when brand pays directly) + - **Breaking**: `billing` is now required in `sync_accounts` request (previously optional). Existing callers that omit `billing` will receive validation errors. Billing is accept-or-reject — sellers cannot silently remap billing. + - Make `account` required on create_media_buy, get_media_buys, sync_creatives, sync_catalogs, sync_audiences, sync_event_sources + - Make `account` required per record on report_usage + - `sync_accounts` no longer returns `account_id` — the seller manages account identifiers internally. Buyers discover IDs via `list_accounts` (explicit model) or use natural keys (implicit model). + - Make `account_id` required in `account.json` (remove conditional if/then — the schema is only used in seller responses where the seller always has an ID) + - Add `account_scope` to account and sync_accounts response schemas + - Add `ACCOUNT_SETUP_REQUIRED` and `ACCOUNT_AMBIGUOUS` error codes + - Add `get_account_financials` task for operator-billed account financial status + +- ff62171: Add `app` catalog type for mobile app install and re-engagement advertising. + + Introduces `AppItem` schema with fields for `bundle_id`, `apple_id`, `platform` (ios/android), store metadata, and deep links. Maps to Google App Campaigns, Apple Search Ads, Meta App Ads, TikTok App Campaigns, and Snapchat App Install Ads. + + Also adds `app_id` to `content-id-type` for conversion event matching and `APP_ITEM_ID` to universal macros for tracking URL substitution. + +- ce439ca: Brand registry lookup, unified enrichment, and membership inheritance +- c872c94: Brand registry as primary company identity source. Member profiles now link to the brand registry via `primary_brand_domain` instead of storing logos and colors directly. Members set up their brand through the brand tools and get a hosted brand.json at `agenticadvertising.org/brands/yourdomain.com/brand.json`. Placing a one-line pointer at `/.well-known/brand.json` makes AgenticAdvertising.org the authoritative brand source for any domain. +- 1051929: Add optional `campaign_ref` field to `get_products` and `create_media_buy` for grouping related operations under a buyer-defined campaign label. Echoed in media buy responses for CRM and ad server correlation. +- 15a64e6: Refactor `CatalogFieldBinding` schema to use a `kind` discriminator field (`"scalar"`, `"asset_pool"`, `"catalog_group"`) instead of `allOf + oneOf` with negative `not` constraints. Scalar and asset pool variants are extracted to `definitions` for reuse in `per_item_bindings`. Generates a clean TypeScript discriminated union instead of triplicated intersections. +- 5b8feea: Add catalog item macros for item-level attribution: SKU, GTIN, OFFERING_ID, JOB_ID, HOTEL_ID, FLIGHT_ID, VEHICLE_ID, LISTING_ID, STORE_ID, PROGRAM_ID, and DESTINATION_ID (mirroring the content_id_type enum), plus CATALOG_ID for catalog-level attribution and CREATIVE_VARIANT_ID for seller-assigned creative variant tracking. Enables closed-loop attribution from impression tracking through conversion events. +- e2e68d3: Add typed catalog assets, field bindings, and feed field mappings. + + **Typed assets on vertical catalog items**: `hotel`, `flight`, `job`, `vehicle`, `real_estate`, `education`, `destination`, and `app` item schemas now support an `assets` array using `OfferingAssetGroup` structure. Enables buyers to provide typed image pools (`images_landscape`, `images_vertical`, `logo`, etc.) alongside existing scalar fields, so formats can declare which asset group to use for each platform-specific slot rather than relying on a single `image_url`. + + **Field bindings on format catalog requirements**: `catalog_requirements` entries now support `field_bindings` — explicit mappings from format template slots (`asset_id`) to catalog item fields (dot-notation path) or typed asset pools (`asset_group_id`). Supports scalar field binding, asset pool binding, and repeatable group iteration over catalog items. Optional — agents can still infer without bindings. + + **Feed field mappings on catalog**: The `Catalog` object now accepts `feed_field_mappings` for normalizing external feeds during `sync_catalogs` ingestion. Supports field renames, named transforms (`date`, `divide`, `boolean`, `split`) with per-transform parameters, static literal injection, and placement of image URLs into typed asset pools. Eliminates the need to preprocess every non-AdCP feed before syncing. + +- 5622c51: Add build capability discovery to creative formats. + + `format.json` gains `input_format_ids` — the source creative formats a format accepts as input manifests (alongside the existing `output_format_ids` for what can be produced). + + `list_creative_formats` gains two new filter parameters: + + - `output_format_ids` — filter to formats that can produce any of the specified outputs + - `input_format_ids` — filter to formats that accept any of the specified formats as input + + Together these let agents ask a creative agent "what can you build?" and query in either direction: "given outputs I need, what inputs do you accept?" or "given inputs I have, what outputs can you produce?" + +- 7b1d51e: Add `get_creative_features` task for creative governance + + Introduces the creative analog of `get_property_features` — a general-purpose task for evaluating creatives and returning feature values. Supports security scanning, creative quality assessment, content categorization, and any other creative evaluation through the same feature-based pattern used by property governance. + + New schemas: + + - `get-creative-features-request.json` — accepts a creative manifest and optional feature_ids filter + - `get-creative-features-response.json` — returns feature results with discriminated union (success/error) + - `creative-feature-result.json` — individual feature evaluation (value, confidence, expires_at, etc.) + + Also adds `creative_features` to the governance section of `get_adcp_capabilities` response, allowing agents to advertise which creative features they can evaluate. + +- 5289d34: Add 3-tier event visibility: public, invite-only listed, and invite-only unlisted. Invite-only events support explicit email invite lists and rule-based access (membership required, org allow-list). Adds `interested` as a distinct registration status for non-invited users who express interest. +- cb5af61: Add `get_media_buys` task for operational campaign monitoring. Returns current media buy status, creative approval state per package, missing format IDs, and optional near-real-time delivery snapshots with `staleness_seconds` to indicate data freshness. Complements `get_media_buy_delivery` which is for authoritative reporting over date ranges. +- c782f66: Note: These changes are breaking relative to earlier betas but no fields removed here were ever in a stable release. + + Add `sync_catalogs` task and unified `Catalog` model. Replace separate `offerings[]` and `product_selectors` fields on `PromotedOfferings` with a typed `Catalog` object that supports inline items, external URL references, and platform-synced catalogs. Expand catalog types beyond offerings and product to include inventory, store, and promotion feeds. Add `sync_catalogs` task with request/response schemas, async response patterns (working, input-required, submitted), per-catalog approval workflow, and item-level review status. Add `catalog_requirements` on `Format` so formats can declare what catalog feeds they need and what fields each must provide. Add `OfferingAssetGroup` schema for structured per-offering creative pools, `OfferingAssetConstraint` for format-level asset requirements, and `geo_targets` on `Offering` for location-specific offerings. Add `account-state` conceptual doc framing Account as the central stateful container in AdCP 3.0. Rename promoted-offerings doc to catalogs to reflect its expanded scope. Add `StoreItem` schema for physical locations within store-type catalogs, with lat/lng coordinates, structured address, operating hours, and tags. Add `Catchment` schema for defining store catchment areas via three methods: isochrone inputs (travel time + transport mode), simple radius, or pre-computed GeoJSON geometry. Add `transport-mode` and `distance-unit` enums. Add industry-vertical catalog types (`hotel`, `flight`, `job`, `vehicle`, `real_estate`, `education`, `destination`) with canonical item schemas for each, drawn from Google Ads, Meta, LinkedIn, and Microsoft platform feed specs. Add shared `Price` schema. Add `linkedin_jobs` feed format. Remove `PromotedOfferings` wrapper — catalogs are now first-class. Creatives reference catalogs via `catalog` field instead of embedding in assets. Remove `promoted_offering` from media-buy and creative-manifest schemas. Add `conversion_events` and `content_id_type` to Catalog for conversion attribution. Rename catalog type `offerings` to `offering` for consistency with other singular type names. Remove `portfolio_ref` from Offering — structured `assets` (OfferingAssetGroup) replaces external portfolio references. Replace `product_selectors` (PromotedProducts) on `get_products` with `catalog` ($ref catalog.json) — one concept, one schema. Delete `promoted-products.json`. Add `catalog_types` to Product so products declare what catalog types they support. Add `matched_ids` and `matched_count` to `catalog_match`, remove `matched_skus`. Add `catalog` field to `package-request` and `package-update` for catalog-driven packages. Add `store_catchments` targeting dimension referencing synced store catalogs. Add `by_catalog_item` delivery breakdown in `get_media_buy_delivery` response for per-item reporting on catalog-driven packages. Update `creative-variant` description to clarify that catalog items rendered as ads are variants. + +- 0e96a78: Add capability declarations for metric optimization goals, cross-channel engagement metrics, video view duration control, and value optimization. + + **New metric kinds** (`optimization_goals` with `kind: 'metric'`): + + - `engagements` — direct ad interaction beyond viewing: social reactions/comments/shares, story/unit opens, interactive overlay taps on CTV, companion banner interactions on audio + - `follows` — new followers, page likes, artist/podcast/channel subscribes + - `saves` — saves, bookmarks, playlist adds, pins + - `profile_visits` — visits to the brand's page, artist page, or channel + + **Video view duration control:** + + - `view_duration_seconds` on metric goals — minimum view duration (in seconds) that qualifies as a `completed_views` event (e.g., 2s, 6s, 15s). Sellers declare supported durations in `metric_optimization.supported_view_durations`. Sellers must reject unsupported values. + + **New event goal target kind:** + + - `maximize_value` — maximize total conversion value within budget without a specific ROAS ratio target. Steers spend toward higher-value conversions. Requires `value_field` on event sources. + + **Product schema additions:** + + - `metric_optimization` — declares which metric kinds a product can optimize for (`supported_metrics`), which view durations are available (`supported_view_durations`), and which target kinds are supported (`supported_targets`). Presence indicates support for `kind: 'metric'` goals without any conversion tracking setup. + - `max_optimization_goals` — maximum number of goals a package can carry. Most social platforms accept only 1. + + **Product schema corrections:** + + - `conversion_tracking.supported_optimization_strategies` renamed to `conversion_tracking.supported_targets` for consistency with `metric_optimization.supported_targets`. Both fields answer the same question: "what can I put in `target.kind`?" + - Target kind enum values aligned across product capabilities and optimization goal schemas. Product `supported_targets` values (`cost_per`, `threshold_rate`, `per_ad_spend`, `maximize_value`) now exactly match `target.kind` values on optimization goals — agents can do direct string comparison. + - `conversion_tracking` description clarified to be for `kind: 'event'` goals only. + + **Delivery metrics additions:** + + - `engagements`, `follows`, `saves`, `profile_visits` count fields added to delivery-metrics.json so buyers can see performance against the new metric optimization goals. + - `completed_views` description updated to acknowledge configurable view duration threshold. + + **Forecastable metrics additions:** + + - `engagements`, `follows`, `saves`, `profile_visits` added to forecastable-metric.json for forecast completeness. + + **Capabilities schema addition:** + + - `media_buy.conversion_tracking.multi_source_event_dedup` — declares whether the seller can deduplicate events across multiple sources. When absent or false, buyers should use a single event source per goal. + + **Optimization goal description clarifications:** + + - `event_sources` references the `multi_source_event_dedup` capability; explains first-source-wins fallback when dedup is unsupported. + - `value_field` and `value_factor` clarified as seller obligations (not optional hints). The seller must use these for value extraction and aggregation. They are not passed to underlying platform APIs. + +- 5b25ccd: Redesign optimization goals with multiple event sources, threshold rates, and attention metrics. + + - `optimization_goal` (singular) → `optimization_goals` (array) on packages + - `OptimizationGoal` is a discriminated union on `kind`: + - `kind: "event"` — optimize for advertiser-tracked conversion events via `event_sources` array of source-type pairs. Seller deduplicates by `event_id` across sources. Each entry can specify `value_field` and `value_factor` for value-based targets. + - `kind: "metric"` — optimize for a seller-native delivery metric with optional `cost_per` or `threshold_rate` target + - Target kinds: `cost_per` (cost per unit), `threshold_rate` (minimum per-impression value), `per_ad_spend` (return ratio on event values), `maximize_value` (maximize total conversion value) + - Metric enum: `clicks`, `views`, `completed_views`, `viewed_seconds`, `attention_seconds`, `attention_score`, `engagements`, `follows`, `saves`, `profile_visits` + - Both kinds support optional `priority` (integer, 1 = highest) for multi-goal packages + - `product.conversion_tracking.supported_targets`: `cost_per`, `per_ad_spend`, `maximize_value` + - `product.metric_optimization.supported_targets`: `cost_per`, `threshold_rate` + +- e6767f2: Add `overlays` to format asset definitions for publisher-controlled elements that render over buyer content. + + Publishers can now declare video player controls, publisher logos, and similar per-asset chrome as `overlays` on individual assets. Each overlay includes `bounds` (pixel or fractional, relative to the asset's own top-left corner) and optional `visual` URLs for light and dark theme variants. Creative agents use this to avoid placing critical buyer content behind publisher chrome when composing creatives. + +- dfcb522: Add structured pricing options to signals and content standards protocols. + + `get_signals` now returns `pricing_options` (array of typed pricing option objects) instead of the legacy `pricing: {cpm, currency}` field. This enables signals agents to offer time-based subscriptions, flat-rate, CPCV, and other pricing models alongside CPM. + + `list_content_standards` / `get_content_standards` now include `pricing_options` on content standards objects as an optional field, using the same structure. Full billing integration for governance agents will be defined when the account setup flow for that protocol is designed. + + `report_usage` has been simplified: `kind` and `operator_id` are removed. The receiving vendor agent already knows what type of service it provides, and the billing operator is captured by the account reference (`brand + operator` form or implied by account setup when using `account_id`). + + `report_usage` now accepts an `idempotency_key` field. Supply a client-generated UUID per request to prevent duplicate billing on retries. + + `activate_signal` now accepts `pricing_option_id`. Pass the pricing option selected from `get_signals` to record the buyer's pricing commitment at activation time. + +- 2957069: Add promoted-offerings-requirement enum and `requires` property to promoted offerings asset requirements (#1040) +- a7feccb: Add property list check and enhancement to the AAO registry API. + + Registry: + + - New `domain_classifications` table with typed entries (`ad_server`, `intermediary`, `cdn`, `tracker`), seeded with ~60 known ad tech infrastructure domains + - New `property_check_reports` table stores full check results by UUID for 7 days + + API: + + - `POST /api/properties/check` — accepts up to 10,000 domains, returns remove/modify/assess/ok buckets and a report ID + - `GET /api/properties/check/:reportId` — retrieve a stored report + + Tools: + + - `check_property_list` MCP tool — runs the check and returns a compact summary + report URL (avoids flooding agent context with thousands of domain entries) + - `enhance_property` MCP tool — analyzes a single unknown domain: WHOIS age check (< 90 days = high risk), adagents.json validation, AI site structure analysis, submits as pending registry entry for Addie review + +- 80afa97: Add sandbox mode as a protocol parameter on all task requests. Sellers declare support via `features.sandbox` in capabilities. Buyers pass `sandbox: true` on any request to run without real platform calls or spend. Replaces the previously documented HTTP header approach (X-Dry-Run, X-Test-Session-ID, X-Mock-Time). +- 8f26baf: Add Swiss (`ch_plz`) and Austrian (`at_plz`) postal code systems to geo targeting. +- b61f271: Add `sync_audiences` task for CRM-based audience management. + + Buyers wrapping closed platforms (LinkedIn, Meta, TikTok, Google Ads) need to upload hashed CRM data before creating campaigns that target or suppress matched audiences. This adds a dedicated task for that workflow, parallel to `sync_event_sources`. + + Schema: + + - New task: `sync_audiences` with request and response schemas + - New core schema: `audience-member.json` — hashed identifiers for CRM list members (email, phone, MAIDs) + - `targeting.json`: add `audience_include` and `audience_exclude` arrays for referencing audiences in `create_media_buy` targeting overlays + + Documentation: + + - New task reference: `docs/media-buy/task-reference/sync_audiences.mdx` + - Updated `docs/media-buy/advanced-topics/targeting.mdx` with `audience_include`/`audience_exclude` overlay documentation + +- 142bcd5: Add `rejected` account status for accounts that were never approved. Previously, `closed` covered both "was active, now terminated" and "seller declined the request", which was counterintuitive. Now `pending_approval` → `rejected` (declined) is distinct from `active` → `closed` (terminated). +- 0cede41: Add CreativeBrief type to BuildCreativeRequest for structured campaign context + +### Patch Changes + +- 24782c2: Add dedicated task reference pages for `sync_accounts` and `list_accounts` under Media Buy Protocol Task Reference. +- 719135b: Move accounts management from manage to admin; fix stale prospect links to removed organizations page. +- 5a90c55: Fix Addie billing status conflating active subscriptions with paid invoices. +- cc6da0c: Increase Addie conversation history from 10 to 20 messages for longer debugging sessions. +- 53e1d65: Add property registry context to Addie's tool reference so she understands what the community property registry is, how data is managed across the three source tiers (authoritative/enriched/community), and when to use each property tool. +- d4f7723: Empty changeset — internal Addie improvements (no protocol changes). +- dce0090: Update Addie's test_adcp_agent tool to use @adcp/client 3.20.0 suite API. +- acd9db7: Addie quality improvements from thread review: accurate spec claims, fictional example names, ads.txt knowledge, shorter deflections, agent type awareness, and session-level web feedback prompt. +- 2d072c1: Clarify push notification config flow in docs and schema. + + - Fix `push_notification_config` placement and naming in webhook docs (task body, not protocol metadata) + - Add `push_notification_config` explicitly to `create_media_buy` request schema + - Fix `operation_id` description: client-generated, echoed by publisher + - Fix HMAC signature format to match wire implementation + +- 2b79286: Clarify that end_date is exclusive in get_media_buy_delivery documentation + + - Add explicit "inclusive" and "exclusive" labels to start_date/end_date parameters + - Add callout explaining start-inclusive, end-exclusive behavior with examples + - Add examples table showing common date range patterns + - Reinforce behavior in Query Behavior section + +- 24b972e: Document save endpoints for brands and properties in registry API docs. +- b311f65: Fix Addie brand management: add missing brand tools to tool reference, prevent save_brand from overwriting enrichment data +- 5e5a3b7: Fix Addie streaming errors, MCP token expiry, and SSE error handling. +- d447e71: Fix three brand identity bugs: has_manifest false when brand.json found, uploaded logo not showing on member card, and "Set up brand" link redirecting to dashboard. +- 5b8feea: Fix build_creative doc examples: remove catalog_id from inline catalogs, add missing offering_id to inline offering items. +- 9f70a06: fix: set CORS headers on MCP 401 responses so OAuth flow can start +- 894e9e9: Empty changeset — no protocol impact. +- 3378218: +- cf3ebb3: Fix schema version alias resolution for prereleases + + - Fix prerelease sorting bug in schema middleware: `/v3/` was resolving to `3.0.0-beta.1` instead of `3.0.0-beta.3` because prereleases were sorted ascending instead of descending + - Update `sync_event_sources` and `log_event` docs to use `/v3/` schema links (these schemas were added in v3) + +- bf19909: Fix API key authentication for WorkOS keys using the new `sk_` prefix. WorkOS changed their key format from `wos_api_key_` to `sk_`, which caused all newer API keys to be rejected by the auth middleware before reaching validation. +- 5418b93: Fix broken schema links in sync_audiences documentation. Changed from `/schemas/v2/` to `/schemas/v1/` since this task was added after the v2.5.x and v3.0.0-beta releases and its schemas only exist in `latest` (which v1 points to). +- 3e7e545: Fix UTF-8 encoding corruption for non-ASCII characters in brand and agent registry files. + + When external servers serve `.well-known/brand.json` or `.well-known/adagents.json` with a non-UTF-8 charset in their `Content-Type` header (e.g. `charset=iso-8859-1`), axios was decoding the UTF-8 response bytes using that charset, corrupting multi-byte characters like Swedish ä/ö/å into mojibake. + + Fix: use `responseType: 'arraybuffer'` on all external fetches so axios delivers raw bytes, then explicitly decode as UTF-8 regardless of what the server declares. + +- 751760a: +- 5b7cbb3: Add Lusha-powered company lookup to referral prospect search: domain-first create form auto-imports companies with full enrichment data. +- 5b7cbb3: Add /manage tier for kitchen cabinet governance access +- 5b7cbb3: Add member referral code system: invite prospects with a personalized landing page, lock the discount to their account on acceptance, and show a 30-day countdown in the membership dashboard. +- 333618c: Download brand logos from Brandfetch CDN to our own PostgreSQL-backed store when enriching brands. Logos are served from `/logos/brands/:domain/:idx` so external agents can download them without hitting Brandfetch hotlinking restrictions. +- e6a62ad: +- b61fcd7: Register all tool sets for web chat, matching Slack channel parity. Previously web chat only had knowledge, billing, and schema tools — brand, directory, property, admin, events, meetings, collaboration, and other tools were missing, causing "Unknown tool" errors. Extracts shared baseline tool registration into a single module both channels import. + ## 3.0.0-beta.3 ### Major Changes diff --git a/dist/schemas/3.0.0-beta.4/a2ui/bound-value.json b/dist/schemas/3.0.0-beta.4/a2ui/bound-value.json new file mode 100644 index 000000000..1f693a0d6 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/a2ui/bound-value.json @@ -0,0 +1,70 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "title": "A2UI Bound Value", + "description": "A value that can be a literal or bound to a path in the data model", + "oneOf": [ + { + "type": "object", + "description": "Literal string value", + "properties": { + "literalString": { + "type": "string", + "description": "Static string value" + } + }, + "required": ["literalString"], + "additionalProperties": false + }, + { + "type": "object", + "description": "Literal number value", + "properties": { + "literalNumber": { + "type": "number", + "description": "Static number value" + } + }, + "required": ["literalNumber"], + "additionalProperties": false + }, + { + "type": "object", + "description": "Literal boolean value", + "properties": { + "literalBoolean": { + "type": "boolean", + "description": "Static boolean value" + } + }, + "required": ["literalBoolean"], + "additionalProperties": false + }, + { + "type": "object", + "description": "Path to data model value", + "properties": { + "path": { + "type": "string", + "description": "JSON pointer path to value in data model (e.g., '/products/0/title')" + } + }, + "required": ["path"], + "additionalProperties": false + }, + { + "type": "object", + "description": "Literal with path binding (sets default and binds)", + "properties": { + "literalString": { + "type": "string" + }, + "path": { + "type": "string" + } + }, + "required": ["literalString", "path"], + "additionalProperties": false + } + ] +} diff --git a/dist/schemas/3.0.0-beta.4/a2ui/component.json b/dist/schemas/3.0.0-beta.4/a2ui/component.json new file mode 100644 index 000000000..9078dc6b2 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/a2ui/component.json @@ -0,0 +1,29 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/a2ui/component.json", + "title": "A2UI Component", + "description": "A component in an A2UI surface", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for this component within the surface" + }, + "parentId": { + "type": "string", + "description": "ID of the parent component (null for root)" + }, + "component": { + "type": "object", + "description": "Component definition (keyed by component type)", + "minProperties": 1, + "maxProperties": 1, + "additionalProperties": { + "type": "object", + "description": "Component properties" + } + } + }, + "required": ["id", "component"], + "additionalProperties": true +} diff --git a/dist/schemas/3.0.0-beta.4/a2ui/si-catalog.json b/dist/schemas/3.0.0-beta.4/a2ui/si-catalog.json new file mode 100644 index 000000000..cbf063ee0 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/a2ui/si-catalog.json @@ -0,0 +1,342 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/a2ui/si-catalog.json", + "title": "SI Component Catalog", + "description": "A2UI component catalog for Sponsored Intelligence", + "definitions": { + "Text": { + "type": "object", + "description": "Text display component", + "properties": { + "text": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Text content to display" + }, + "variant": { + "type": "string", + "enum": ["body", "heading", "caption", "label"], + "default": "body" + } + }, + "required": ["text"] + }, + "Button": { + "type": "object", + "description": "Interactive button component", + "properties": { + "label": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Button label text" + }, + "action": { + "type": "object", + "description": "Action to trigger on click", + "properties": { + "name": { + "type": "string", + "description": "Action identifier" + }, + "context": { + "type": "object", + "description": "Context data to include with action", + "additionalProperties": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json" + } + } + }, + "required": ["name"] + }, + "variant": { + "type": "string", + "enum": ["primary", "secondary", "text"], + "default": "primary" + }, + "disabled": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json" + } + }, + "required": ["label", "action"] + }, + "Link": { + "type": "object", + "description": "Hyperlink component", + "properties": { + "label": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Link text" + }, + "url": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "URL to navigate to" + }, + "external": { + "type": "boolean", + "description": "Opens in new tab if true", + "default": true + } + }, + "required": ["label", "url"] + }, + "Image": { + "type": "object", + "description": "Image display component", + "properties": { + "src": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Image source URL" + }, + "alt": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Alt text for accessibility" + }, + "width": { + "type": "integer", + "description": "Image width in pixels" + }, + "height": { + "type": "integer", + "description": "Image height in pixels" + } + }, + "required": ["src", "alt"] + }, + "Card": { + "type": "object", + "description": "Card container for grouped content", + "properties": { + "title": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Card title" + }, + "subtitle": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Card subtitle" + }, + "image": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Card image URL" + }, + "badge": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Badge text (e.g., 'New', 'Sale')" + }, + "action": { + "type": "object", + "description": "Action to trigger on card click", + "properties": { + "name": { "type": "string" }, + "context": { + "type": "object", + "additionalProperties": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json" + } + } + }, + "required": ["name"] + }, + "children": { + "type": "array", + "description": "Child component IDs", + "items": { "type": "string" } + } + }, + "required": ["title"] + }, + "ProductCard": { + "type": "object", + "description": "Product display card (SI-specific)", + "properties": { + "title": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Product name" + }, + "price": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Price display string" + }, + "image": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Product image URL" + }, + "description": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Product description" + }, + "badge": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Badge text (e.g., 'Best Seller')" + }, + "ctaLabel": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "CTA button label" + }, + "action": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "context": { + "type": "object", + "additionalProperties": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json" + } + } + }, + "required": ["name"] + } + }, + "required": ["title", "price"] + }, + "List": { + "type": "object", + "description": "Data-bound list component", + "properties": { + "items": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Path to array in data model" + }, + "template": { + "type": "object", + "description": "Template for list items", + "properties": { + "componentId": { + "type": "string", + "description": "ID of component to use as template" + } + }, + "required": ["componentId"] + }, + "emptyMessage": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Message to show when list is empty" + }, + "layout": { + "type": "string", + "enum": ["vertical", "horizontal", "grid"], + "default": "vertical" + } + }, + "required": ["items", "template"] + }, + "Row": { + "type": "object", + "description": "Horizontal layout container", + "properties": { + "children": { + "type": "array", + "description": "Child component IDs", + "items": { "type": "string" } + }, + "gap": { + "type": "string", + "description": "Gap between children", + "default": "8px" + }, + "align": { + "type": "string", + "enum": ["start", "center", "end", "stretch"], + "default": "center" + }, + "justify": { + "type": "string", + "enum": ["start", "center", "end", "between", "around"], + "default": "start" + } + }, + "required": ["children"] + }, + "Column": { + "type": "object", + "description": "Vertical layout container", + "properties": { + "children": { + "type": "array", + "description": "Child component IDs", + "items": { "type": "string" } + }, + "gap": { + "type": "string", + "description": "Gap between children", + "default": "8px" + }, + "align": { + "type": "string", + "enum": ["start", "center", "end", "stretch"], + "default": "stretch" + } + }, + "required": ["children"] + }, + "IntegrationAction": { + "type": "object", + "description": "MCP/A2A integration action button (SI-specific)", + "properties": { + "type": { + "type": "string", + "enum": ["mcp", "a2a"], + "description": "Integration type" + }, + "label": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Button label" + }, + "url": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/bound-value.json", + "description": "Integration endpoint URL" + }, + "highlighted": { + "type": "boolean", + "description": "Visually emphasize this action", + "default": false + } + }, + "required": ["type", "label"] + }, + "AppHandoff": { + "type": "object", + "description": "Platform app handoff (SI-specific)", + "properties": { + "apps": { + "type": "object", + "description": "Platform-specific app configurations", + "additionalProperties": { + "type": "object", + "properties": { + "appId": { "type": "string" }, + "deepLink": { "type": "string" }, + "url": { "type": "string", "format": "uri" } + } + } + } + }, + "required": ["apps"] + } + }, + "type": "object", + "properties": { + "catalogId": { + "type": "string", + "const": "si-standard", + "description": "SI standard component catalog" + }, + "components": { + "type": "array", + "description": "Available component types", + "items": { + "type": "string", + "enum": [ + "Text", + "Button", + "Link", + "Image", + "Card", + "ProductCard", + "List", + "Row", + "Column", + "IntegrationAction", + "AppHandoff" + ] + } + } + } +} diff --git a/dist/schemas/3.0.0-beta.4/a2ui/surface.json b/dist/schemas/3.0.0-beta.4/a2ui/surface.json new file mode 100644 index 000000000..69f7c0d52 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/a2ui/surface.json @@ -0,0 +1,36 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/a2ui/surface.json", + "title": "A2UI Surface", + "description": "A contiguous UI region containing components", + "type": "object", + "properties": { + "surfaceId": { + "type": "string", + "description": "Unique identifier for this surface" + }, + "catalogId": { + "type": "string", + "description": "Component catalog to use for rendering", + "default": "standard" + }, + "components": { + "type": "array", + "description": "Flat list of components (adjacency list structure)", + "items": { + "$ref": "/schemas/3.0.0-beta.4/a2ui/component.json" + } + }, + "rootId": { + "type": "string", + "description": "ID of the root component (if not specified, first component is root)" + }, + "dataModel": { + "type": "object", + "description": "Application data that components can bind to", + "additionalProperties": true + } + }, + "required": ["surfaceId", "components"], + "additionalProperties": true +} diff --git a/dist/schemas/3.0.0-beta.4/a2ui/user-action.json b/dist/schemas/3.0.0-beta.4/a2ui/user-action.json new file mode 100644 index 000000000..fb0c586bc --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/a2ui/user-action.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/a2ui/user-action.json", + "title": "A2UI User Action", + "description": "User interaction event sent from client to agent", + "type": "object", + "properties": { + "surfaceId": { + "type": "string", + "description": "ID of the surface where the action occurred" + }, + "componentId": { + "type": "string", + "description": "ID of the component that triggered the action" + }, + "action": { + "type": "object", + "description": "The action that was triggered", + "properties": { + "name": { + "type": "string", + "description": "Action identifier (e.g., 'view_product', 'add_to_cart')" + }, + "context": { + "type": "object", + "description": "Context data resolved from data model bindings", + "additionalProperties": true + } + }, + "required": ["name"], + "additionalProperties": true + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "When the action occurred" + } + }, + "required": ["surfaceId", "componentId", "action"], + "additionalProperties": true +} diff --git a/dist/schemas/3.0.0-beta.4/account/get-account-financials-request.json b/dist/schemas/3.0.0-beta.4/account/get-account-financials-request.json new file mode 100644 index 000000000..8f5628df6 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/account/get-account-financials-request.json @@ -0,0 +1,68 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/account/get-account-financials-request.json", + "title": "Get Account Financials Request", + "description": "Request financial status for an operator-billed account. Returns spend summary, credit/balance status, and invoice history. Only applicable when the seller declares account_financials capability.", + "type": "object", + "properties": { + "account": { + "$ref": "/schemas/3.0.0-beta.4/core/account-ref.json", + "description": "Account to query financials for. Must be an operator-billed account." + }, + "period": { + "type": "object", + "description": "Date range for the spend summary. Defaults to the current billing cycle if omitted.", + "properties": { + "start": { + "type": "string", + "format": "date", + "description": "Period start (ISO 8601 date)" + }, + "end": { + "type": "string", + "format": "date", + "description": "Period end (ISO 8601 date)" + } + }, + "required": ["start", "end"] + }, + "context": { + "$ref": "/schemas/3.0.0-beta.4/core/context.json" + }, + "ext": { + "$ref": "/schemas/3.0.0-beta.4/core/ext.json" + } + }, + "required": ["account"], + "additionalProperties": true, + "examples": [ + { + "description": "Query by account ID for current billing cycle", + "data": { + "account": { "account_id": "acc_acme_001" } + } + }, + { + "description": "Query by natural key for a specific period", + "data": { + "account": { + "brand": { "domain": "acme-corp.com" }, + "operator": "acme-corp.com" + }, + "period": { + "start": "2026-01-01", + "end": "2026-01-31" + } + } + }, + { + "description": "Agency querying financials for a client account", + "data": { + "account": { + "brand": { "domain": "nova-brands.com", "brand_id": "spark" }, + "operator": "pinnacle-media.com" + } + } + } + ] +} diff --git a/dist/schemas/3.0.0-beta.4/account/get-account-financials-response.json b/dist/schemas/3.0.0-beta.4/account/get-account-financials-response.json new file mode 100644 index 000000000..7155c6650 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/account/get-account-financials-response.json @@ -0,0 +1,275 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/account/get-account-financials-response.json", + "title": "Get Account Financials Response", + "description": "Financial status for an operator-billed account. Returns spend summary, credit/balance status, payment status, and invoice history. The level of detail varies by seller — only account, currency, and period are guaranteed on success.", + "type": "object", + "oneOf": [ + { + "title": "GetAccountFinancialsSuccess", + "description": "Financial data retrieved successfully", + "type": "object", + "properties": { + "account": { + "$ref": "/schemas/3.0.0-beta.4/core/account-ref.json", + "description": "Account reference, echoed from the request" + }, + "currency": { + "type": "string", + "pattern": "^[A-Z]{3}$", + "description": "ISO 4217 currency code for all monetary amounts in this response" + }, + "period": { + "type": "object", + "description": "The actual period covered by spend data. May differ from the requested period if the seller adjusts to billing cycle boundaries.", + "properties": { + "start": { + "type": "string", + "format": "date", + "description": "Period start (ISO 8601 date)" + }, + "end": { + "type": "string", + "format": "date", + "description": "Period end (ISO 8601 date)" + } + }, + "required": ["start", "end"] + }, + "spend": { + "type": "object", + "description": "Spend summary for the period", + "properties": { + "total_spend": { + "type": "number", + "minimum": 0, + "description": "Total spend in the period, in currency" + }, + "media_buy_count": { + "type": "integer", + "minimum": 0, + "description": "Number of active media buys in the period" + } + }, + "required": ["total_spend"] + }, + "credit": { + "type": "object", + "description": "Credit status. Present for credit-based accounts (payment_terms like net_30).", + "properties": { + "credit_limit": { + "type": "number", + "minimum": 0, + "description": "Maximum outstanding balance allowed" + }, + "available_credit": { + "type": "number", + "description": "Remaining credit available (credit_limit minus outstanding balance)" + }, + "utilization_percent": { + "type": "number", + "minimum": 0, + "maximum": 100, + "description": "Credit utilization as a percentage (0-100)" + } + }, + "required": ["credit_limit", "available_credit"] + }, + "balance": { + "type": "object", + "description": "Prepay balance. Present for prepay accounts.", + "properties": { + "available": { + "type": "number", + "minimum": 0, + "description": "Remaining prepaid balance" + }, + "last_top_up": { + "type": "object", + "description": "Most recent balance top-up", + "properties": { + "amount": { + "type": "number", + "minimum": 0, + "description": "Top-up amount" + }, + "date": { + "type": "string", + "format": "date", + "description": "Date of top-up" + } + }, + "required": ["amount", "date"] + } + }, + "required": ["available"] + }, + "payment_status": { + "type": "string", + "enum": ["current", "past_due", "suspended"], + "description": "Overall payment status. current: all obligations met. past_due: one or more invoices overdue. suspended: account suspended due to payment issues." + }, + "payment_terms": { + "type": "string", + "description": "Payment terms in effect (e.g., 'net_30', 'prepay')" + }, + "invoices": { + "type": "array", + "description": "Recent invoices. Sellers may limit the number returned.", + "items": { + "type": "object", + "properties": { + "invoice_id": { + "type": "string", + "description": "Seller-assigned invoice identifier" + }, + "period": { + "type": "object", + "description": "Billing period covered by this invoice", + "properties": { + "start": { "type": "string", "format": "date" }, + "end": { "type": "string", "format": "date" } + }, + "required": ["start", "end"] + }, + "amount": { + "type": "number", + "minimum": 0, + "description": "Invoice total in currency" + }, + "status": { + "type": "string", + "enum": ["draft", "issued", "paid", "past_due", "void"], + "description": "Invoice status" + }, + "due_date": { + "type": "string", + "format": "date", + "description": "Payment due date" + }, + "paid_date": { + "type": "string", + "format": "date", + "description": "Date payment was received. Present when status is 'paid'." + } + }, + "required": ["invoice_id", "amount", "status"] + } + }, + "context": { + "$ref": "/schemas/3.0.0-beta.4/core/context.json" + }, + "ext": { + "$ref": "/schemas/3.0.0-beta.4/core/ext.json" + } + }, + "required": ["account", "currency", "period"], + "additionalProperties": true, + "not": { + "required": ["errors"] + } + }, + { + "title": "GetAccountFinancialsError", + "description": "Operation failed — financials not available", + "type": "object", + "properties": { + "errors": { + "type": "array", + "description": "Operation-level errors", + "items": { + "$ref": "/schemas/3.0.0-beta.4/core/error.json" + }, + "minItems": 1 + }, + "context": { + "$ref": "/schemas/3.0.0-beta.4/core/context.json" + }, + "ext": { + "$ref": "/schemas/3.0.0-beta.4/core/ext.json" + } + }, + "required": ["errors"], + "additionalProperties": true, + "not": { + "anyOf": [ + { "required": ["account"] }, + { "required": ["currency"] }, + { "required": ["period"] } + ] + } + } + ], + "examples": [ + { + "description": "Credit account — current, with invoice history", + "data": { + "account": { "account_id": "acc_acme_001" }, + "currency": "USD", + "period": { + "start": "2026-02-01", + "end": "2026-02-28" + }, + "spend": { + "total_spend": 45230.00, + "media_buy_count": 3 + }, + "credit": { + "credit_limit": 100000.00, + "available_credit": 54770.00, + "utilization_percent": 45.23 + }, + "payment_status": "current", + "payment_terms": "net_30", + "invoices": [ + { + "invoice_id": "inv_2026_01", + "period": { "start": "2026-01-01", "end": "2026-01-31" }, + "amount": 38500.00, + "status": "paid", + "due_date": "2026-02-28", + "paid_date": "2026-02-15" + } + ] + } + }, + { + "description": "Prepay account with low balance", + "data": { + "account": { + "brand": { "domain": "acme-corp.com" }, + "operator": "acme-corp.com" + }, + "currency": "USD", + "period": { + "start": "2026-02-01", + "end": "2026-02-28" + }, + "spend": { + "total_spend": 8200.00, + "media_buy_count": 2 + }, + "balance": { + "available": 1800.00, + "last_top_up": { + "amount": 10000.00, + "date": "2026-02-01" + } + }, + "payment_status": "current", + "payment_terms": "prepay" + } + }, + { + "description": "Agent-billed account — not supported", + "data": { + "errors": [ + { + "code": "BILLING_MODEL_NOT_SUPPORTED", + "message": "Financial data is not available for agent-billed accounts. The agent's own billing system is the source of truth." + } + ] + } + } + ] +} diff --git a/dist/schemas/3.0.0-beta.4/account/list-accounts-request.json b/dist/schemas/3.0.0-beta.4/account/list-accounts-request.json new file mode 100644 index 000000000..09fd4732d --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/account/list-accounts-request.json @@ -0,0 +1,36 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/account/list-accounts-request.json", + "title": "List Accounts Request", + "description": "Request parameters for listing accounts accessible to the authenticated agent", + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "active", + "pending_approval", + "rejected", + "payment_required", + "suspended", + "closed" + ], + "description": "Filter accounts by status. Omit to return accounts in all statuses." + }, + "pagination": { + "$ref": "/schemas/3.0.0-beta.4/core/pagination-request.json" + }, + "sandbox": { + "type": "boolean", + "description": "Filter by sandbox status. true returns only sandbox accounts, false returns only production accounts. Omit to return all accounts." + }, + "context": { + "$ref": "/schemas/3.0.0-beta.4/core/context.json" + }, + "ext": { + "$ref": "/schemas/3.0.0-beta.4/core/ext.json" + } + }, + "required": [], + "additionalProperties": true +} diff --git a/dist/schemas/3.0.0-beta.4/account/list-accounts-response.json b/dist/schemas/3.0.0-beta.4/account/list-accounts-response.json new file mode 100644 index 000000000..b1ef6e01b --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/account/list-accounts-response.json @@ -0,0 +1,97 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/account/list-accounts-response.json", + "title": "List Accounts Response", + "description": "Response payload for list_accounts task", + "type": "object", + "properties": { + "accounts": { + "type": "array", + "description": "Array of accounts accessible to the authenticated agent", + "items": { + "$ref": "/schemas/3.0.0-beta.4/core/account.json" + } + }, + "errors": { + "type": "array", + "description": "Task-specific errors and warnings", + "items": { + "$ref": "/schemas/3.0.0-beta.4/core/error.json" + } + }, + "pagination": { + "$ref": "/schemas/3.0.0-beta.4/core/pagination-response.json" + }, + "context": { + "$ref": "/schemas/3.0.0-beta.4/core/context.json" + }, + "ext": { + "$ref": "/schemas/3.0.0-beta.4/core/ext.json" + } + }, + "required": ["accounts"], + "additionalProperties": true, + "examples": [ + { + "description": "Agency with multiple client accounts", + "data": { + "accounts": [ + { + "account_id": "acc_acme_pinnacle", + "name": "Acme c/o Pinnacle", + "advertiser": "Acme Corp", + "billing_proxy": "Pinnacle Media", + "brand": { "domain": "acme-corp.com" }, + "operator": "pinnacle-media.com", + "billing": "operator", + "account_scope": "operator_brand", + "status": "active" + }, + { + "account_id": "acc_nova_pinnacle", + "name": "Nova c/o Pinnacle", + "advertiser": "Nova Brands", + "billing_proxy": "Pinnacle Media", + "brand": { "domain": "nova-brands.com", "brand_id": "spark" }, + "operator": "pinnacle-media.com", + "billing": "operator", + "account_scope": "operator_brand", + "status": "active" + }, + { + "account_id": "acc_pinnacle", + "name": "Pinnacle", + "advertiser": "Pinnacle Media", + "brand": { "domain": "pinnacle-media.com" }, + "operator": "pinnacle-media.com", + "billing": "operator", + "account_scope": "operator", + "status": "active" + } + ], + "pagination": { + "has_more": false, + "total_count": 3 + } + } + }, + { + "description": "Direct advertiser with single account", + "data": { + "accounts": [ + { + "account_id": "acc_acme_direct", + "name": "Acme", + "advertiser": "Acme Corp", + "brand": { "domain": "acme-corp.com" }, + "operator": "acme-corp.com", + "billing": "operator", + "account_scope": "brand", + "status": "active", + "rate_card": "acme_vip_2024" + } + ] + } + } + ] +} diff --git a/dist/schemas/3.0.0-beta.4/account/report-usage-request.json b/dist/schemas/3.0.0-beta.4/account/report-usage-request.json new file mode 100644 index 000000000..827e94b8f --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/account/report-usage-request.json @@ -0,0 +1,144 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/account/report-usage-request.json", + "title": "Report Usage Request", + "description": "Reports how a vendor's service was consumed after campaign delivery. Used by orchestrators (DSPs, storefronts) to inform vendor agents (signals, governance, creative) what was used so the vendor can track earned revenue and verify billing. Records can span multiple accounts and campaigns in a single request.", + "type": "object", + "properties": { + "idempotency_key": { + "type": "string", + "description": "Client-generated unique key for this request. If a request with the same key has already been accepted, the server returns the original response without re-processing. Use a UUID or other unique identifier. Prevents duplicate billing on retries." + }, + "reporting_period": { + "type": "object", + "description": "The time range covered by this usage report. Applies to all records in the request.", + "properties": { + "start": { + "type": "string", + "format": "date-time", + "description": "Start of the reporting period (inclusive), in UTC." + }, + "end": { + "type": "string", + "format": "date-time", + "description": "End of the reporting period (inclusive), in UTC." + } + }, + "required": ["start", "end"], + "additionalProperties": false + }, + "usage": { + "type": "array", + "description": "One or more usage records. Each record is self-contained: it carries its own account and buyer_campaign_ref, allowing a single request to span multiple accounts and campaigns.", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "account": { + "$ref": "/schemas/3.0.0-beta.4/core/account-ref.json", + "description": "Account for this usage record." + }, + "buyer_campaign_ref": { + "type": "string", + "description": "The buyer's campaign reference (e.g., a media_buy_id). Used to group records by campaign." + }, + "vendor_cost": { + "type": "number", + "minimum": 0, + "description": "Amount owed to the vendor for this record, denominated in currency." + }, + "currency": { + "type": "string", + "pattern": "^[A-Z]{3}$", + "description": "ISO 4217 currency code." + }, + "pricing_option_id": { + "type": "string", + "description": "Pricing option identifier from the vendor's discovery response (e.g., get_signals, list_content_standards). The vendor uses this to verify the correct rate was applied." + }, + "impressions": { + "type": "integer", + "minimum": 0, + "description": "Impressions delivered using this vendor service." + }, + "media_spend": { + "type": "number", + "minimum": 0, + "description": "Media spend in currency for the period. Required when a percent_of_media pricing model was used, so the vendor can verify the applied rate." + }, + "signal_agent_segment_id": { + "type": "string", + "description": "Signal identifier from get_signals. Required for signals agents." + }, + "standards_id": { + "type": "string", + "description": "Content standards configuration identifier. Required for governance agents." + } + }, + "required": ["account", "vendor_cost", "currency"], + "additionalProperties": true + } + }, + "context": { + "$ref": "/schemas/3.0.0-beta.4/core/context.json" + }, + "ext": { + "$ref": "/schemas/3.0.0-beta.4/core/ext.json" + } + }, + "required": ["reporting_period", "usage"], + "additionalProperties": true, + "examples": [ + { + "description": "Signal usage for a single campaign", + "data": { + "idempotency_key": "550e8400-e29b-41d4-a716-446655440000", + "reporting_period": { + "start": "2025-03-01T00:00:00Z", + "end": "2025-03-31T23:59:59Z" + }, + "usage": [ + { + "account": { "account_id": "acct_pinnacle_signals" }, + "buyer_campaign_ref": "mb_spring_launch_001", + "signal_agent_segment_id": "luxury_auto_intenders", + "pricing_option_id": "po_lux_auto_cpm", + "impressions": 4200000, + "media_spend": 21000.00, + "vendor_cost": 2100.00, + "currency": "USD" + } + ] + } + }, + { + "description": "Multi-account batch across two campaigns", + "data": { + "reporting_period": { + "start": "2025-03-01T00:00:00Z", + "end": "2025-03-31T23:59:59Z" + }, + "usage": [ + { + "account": { "account_id": "acct_pinnacle_signals" }, + "buyer_campaign_ref": "mb_spring_q1_001", + "signal_agent_segment_id": "luxury_auto_intenders", + "pricing_option_id": "po_lux_auto_cpm", + "impressions": 2100000, + "vendor_cost": 1050.00, + "currency": "USD" + }, + { + "account": { "account_id": "acct_nova" }, + "buyer_campaign_ref": "mb_summer_preview_002", + "signal_agent_segment_id": "eco_conscious_shoppers", + "pricing_option_id": "po_eco_cpm", + "impressions": 800000, + "vendor_cost": 400.00, + "currency": "USD" + } + ] + } + } + ] +} diff --git a/dist/schemas/3.0.0-beta.4/account/report-usage-response.json b/dist/schemas/3.0.0-beta.4/account/report-usage-response.json new file mode 100644 index 000000000..a5e979d41 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/account/report-usage-response.json @@ -0,0 +1,54 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/account/report-usage-response.json", + "title": "Report Usage Response", + "description": "Response from report_usage. Partial acceptance is valid — records that pass validation are stored even when others fail.", + "type": "object", + "properties": { + "accepted": { + "type": "integer", + "minimum": 0, + "description": "Number of usage records successfully stored." + }, + "errors": { + "type": "array", + "description": "Validation errors for individual records. The field property identifies which record failed (e.g., 'usage[1].pricing_option_id').", + "items": { + "$ref": "/schemas/3.0.0-beta.4/core/error.json" + } + }, + "sandbox": { + "type": "boolean", + "description": "When true, the account is a sandbox account and no billing occurred." + }, + "context": { + "$ref": "/schemas/3.0.0-beta.4/core/context.json" + }, + "ext": { + "$ref": "/schemas/3.0.0-beta.4/core/ext.json" + } + }, + "required": ["accepted"], + "additionalProperties": true, + "examples": [ + { + "description": "All records accepted", + "data": { + "accepted": 2 + } + }, + { + "description": "Partial acceptance — one record failed validation", + "data": { + "accepted": 1, + "errors": [ + { + "code": "INVALID_PRICING_OPTION", + "message": "pricing_option_id 'po_unknown' does not exist on this account", + "field": "usage[1].pricing_option_id" + } + ] + } + } + ] +} diff --git a/dist/schemas/3.0.0-beta.4/account/sync-accounts-request.json b/dist/schemas/3.0.0-beta.4/account/sync-accounts-request.json new file mode 100644 index 000000000..dadc369b6 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/account/sync-accounts-request.json @@ -0,0 +1,119 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/account/sync-accounts-request.json", + "title": "Sync Accounts Request", + "description": "Sync advertiser accounts with a seller using upsert semantics. The agent declares which brands it represents, who operates on each brand's behalf, and the billing model. The seller provisions or links accounts accordingly, returning per-account status.", + "type": "object", + "properties": { + "accounts": { + "type": "array", + "description": "Advertiser accounts to sync", + "items": { + "type": "object", + "description": "An advertiser account the agent wants to operate on the seller", + "properties": { + "brand": { + "$ref": "/schemas/3.0.0-beta.4/core/brand-ref.json", + "description": "Brand reference identifying the advertiser. Uses the brand's house domain and optional brand_id from brand.json." + }, + "operator": { + "type": "string", + "description": "Domain of the entity operating on the brand's behalf (e.g., 'pinnacle-media.com'). When the brand operates directly, this is the brand's domain. Verified against the brand's authorized_operators in brand.json.", + "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$" + }, + "billing": { + "type": "string", + "enum": [ + "operator", + "agent" + ], + "description": "Who should be invoiced. operator: seller invoices the operator (agency or brand buying direct). agent: agent consolidates billing across brands. The seller must either accept this billing model or reject the request." + }, + "sandbox": { + "type": "boolean", + "description": "When true, provision this as a sandbox account. No real platform calls or billing. Sandbox accounts are identified by account_id in subsequent requests." + } + }, + "required": [ + "brand", + "operator", + "billing" + ], + "additionalProperties": true + }, + "maxItems": 1000 + }, + "delete_missing": { + "type": "boolean", + "default": false, + "description": "When true, accounts previously synced by this agent but not included in this request will be deactivated. Scoped to the authenticated agent — does not affect accounts managed by other agents. Use with caution." + }, + "dry_run": { + "type": "boolean", + "default": false, + "description": "When true, preview what would change without applying. Returns what would be created/updated/deactivated." + }, + "push_notification_config": { + "$ref": "/schemas/3.0.0-beta.4/core/push-notification-config.json", + "description": "Webhook for async notifications when account status changes (e.g., pending_approval transitions to active)." + }, + "context": { + "$ref": "/schemas/3.0.0-beta.4/core/context.json" + }, + "ext": { + "$ref": "/schemas/3.0.0-beta.4/core/ext.json" + } + }, + "required": [ + "accounts" + ], + "additionalProperties": true, + "examples": [ + { + "description": "Agency syncing multiple advertisers with different billing", + "data": { + "accounts": [ + { + "brand": { "domain": "nova-brands.com", "brand_id": "spark" }, + "operator": "pinnacle-media.com", + "billing": "operator" + }, + { + "brand": { "domain": "nova-brands.com", "brand_id": "glow" }, + "operator": "pinnacle-media.com", + "billing": "agent" + } + ] + } + }, + { + "description": "Brand buying direct", + "data": { + "accounts": [ + { + "brand": { "domain": "acme-corp.com" }, + "operator": "acme-corp.com", + "billing": "operator" + } + ] + } + }, + { + "description": "Agent consolidating billing for all advertisers", + "data": { + "accounts": [ + { + "brand": { "domain": "nova-brands.com", "brand_id": "spark" }, + "operator": "pinnacle-media.com", + "billing": "agent" + }, + { + "brand": { "domain": "nova-brands.com", "brand_id": "glow" }, + "operator": "pinnacle-media.com", + "billing": "agent" + } + ] + } + } + ] +} diff --git a/dist/schemas/3.0.0-beta.4/account/sync-accounts-response.json b/dist/schemas/3.0.0-beta.4/account/sync-accounts-response.json new file mode 100644 index 000000000..e816d18bb --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/account/sync-accounts-response.json @@ -0,0 +1,271 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/account/sync-accounts-response.json", + "title": "Sync Accounts Response", + "description": "Response from account sync operation. Returns per-account results with status and billing, or operation-level errors on complete failure.", + "type": "object", + "oneOf": [ + { + "title": "SyncAccountsSuccess", + "description": "Sync operation processed accounts (individual accounts may be pending or have action=failed)", + "type": "object", + "properties": { + "dry_run": { + "type": "boolean", + "description": "Whether this was a dry run (no actual changes made)" + }, + "accounts": { + "type": "array", + "description": "Results for each account processed", + "items": { + "type": "object", + "properties": { + "brand": { + "$ref": "/schemas/3.0.0-beta.4/core/brand-ref.json", + "description": "Brand reference, echoed from the request" + }, + "operator": { + "type": "string", + "description": "Operator domain, echoed from request" + }, + "name": { + "type": "string", + "description": "Human-readable account name assigned by the seller" + }, + "action": { + "type": "string", + "enum": [ + "created", + "updated", + "unchanged", + "failed" + ], + "description": "Action taken for this account. created: new account provisioned. updated: existing account modified. unchanged: no changes needed. failed: could not process (see errors)." + }, + "status": { + "type": "string", + "enum": [ + "active", + "pending_approval", + "rejected", + "payment_required", + "suspended", + "closed" + ], + "description": "Account status. active: ready for use. pending_approval: seller reviewing (credit, legal). rejected: seller declined the account request. payment_required: credit limit reached or funds depleted. suspended: was active, now paused. closed: was active, now terminated." + }, + "billing": { + "type": "string", + "enum": [ + "operator", + "agent" + ], + "description": "Who is invoiced on this account. Matches the requested billing model." + }, + "account_scope": { + "type": "string", + "enum": ["operator", "brand", "operator_brand", "agent"], + "description": "How the seller scoped this account. operator: shared across all brands for this operator. brand: shared across all operators for this brand. operator_brand: dedicated to this operator+brand pair. agent: the agent's default account." + }, + "setup": { + "type": "object", + "description": "Setup information for pending accounts. Provides the agent (or human) with next steps to complete account activation.", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL where the human can complete the required action (credit application, legal agreement, add funds)" + }, + "message": { + "type": "string", + "description": "Human-readable description of what's needed" + }, + "expires_at": { + "type": "string", + "format": "date-time", + "description": "When this setup link expires" + } + }, + "required": [ + "message" + ], + "additionalProperties": true + }, + "rate_card": { + "type": "string", + "description": "Rate card applied to this account" + }, + "payment_terms": { + "type": "string", + "description": "Payment terms (e.g., 'net_30', 'prepay')" + }, + "credit_limit": { + "type": "object", + "properties": { + "amount": { + "type": "number", + "minimum": 0 + }, + "currency": { + "type": "string", + "pattern": "^[A-Z]{3}$" + } + }, + "required": [ + "amount", + "currency" + ] + }, + "errors": { + "type": "array", + "description": "Per-account errors (only present when action is 'failed')", + "items": { + "$ref": "/schemas/3.0.0-beta.4/core/error.json" + } + }, + "warnings": { + "type": "array", + "description": "Non-fatal warnings about this account", + "items": { + "type": "string" + } + }, + "sandbox": { + "type": "boolean", + "description": "Whether this is a sandbox account, echoed from the request." + } + }, + "required": [ + "brand", + "operator", + "action", + "status" + ], + "additionalProperties": true + } + }, + "context": { + "$ref": "/schemas/3.0.0-beta.4/core/context.json" + }, + "ext": { + "$ref": "/schemas/3.0.0-beta.4/core/ext.json" + } + }, + "required": [ + "accounts" + ], + "additionalProperties": true, + "not": { + "required": [ + "errors" + ] + } + }, + { + "title": "SyncAccountsError", + "description": "Operation failed completely, no accounts were processed", + "type": "object", + "properties": { + "errors": { + "type": "array", + "description": "Operation-level errors (e.g., authentication failure, service unavailable)", + "items": { + "$ref": "/schemas/3.0.0-beta.4/core/error.json" + }, + "minItems": 1 + }, + "context": { + "$ref": "/schemas/3.0.0-beta.4/core/context.json" + }, + "ext": { + "$ref": "/schemas/3.0.0-beta.4/core/ext.json" + } + }, + "required": [ + "errors" + ], + "additionalProperties": true, + "not": { + "anyOf": [ + { + "required": [ + "accounts" + ] + }, + { + "required": [ + "dry_run" + ] + } + ] + } + } + ], + "examples": [ + { + "description": "Mixed results — one active, one pending approval", + "data": { + "accounts": [ + { + "brand": { "domain": "nova-brands.com", "brand_id": "spark" }, + "operator": "pinnacle-media.com", + "name": "Spark (via Pinnacle)", + "action": "created", + "status": "active", + "billing": "operator", + "account_scope": "operator_brand" + }, + { + "brand": { "domain": "nova-brands.com", "brand_id": "glow" }, + "operator": "pinnacle-media.com", + "name": "Glow", + "action": "created", + "status": "pending_approval", + "billing": "operator", + "account_scope": "operator_brand", + "setup": { + "url": "https://seller.example.com/advertiser-onboard", + "message": "Complete advertiser registration and credit application", + "expires_at": "2026-03-10T00:00:00Z" + } + } + ] + } + }, + { + "description": "Rejected account — no account_id assigned", + "data": { + "accounts": [ + { + "brand": { "domain": "acme-corp.com", "brand_id": "clearance" }, + "operator": "acme-corp.com", + "action": "created", + "status": "rejected", + "warnings": [ + "Account request declined: advertiser category not accepted on this platform." + ] + } + ] + } + }, + { + "description": "Unsupported billing — seller rejects the request", + "data": { + "accounts": [ + { + "brand": { "domain": "acme-corp.com" }, + "operator": "acme-corp.com", + "action": "failed", + "status": "rejected", + "errors": [ + { + "code": "BILLING_NOT_SUPPORTED", + "message": "Operator billing is not supported. This seller only accepts agent billing." + } + ] + } + ] + } + } + ] +} diff --git a/dist/schemas/3.0.0-beta.4/adagents.json b/dist/schemas/3.0.0-beta.4/adagents.json new file mode 100644 index 000000000..57521654a --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/adagents.json @@ -0,0 +1,762 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/adagents.json", + "title": "AdCP Agents Authorization", + "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.", + "oneOf": [ + { + "type": "object", + "description": "URL reference variant - points to the authoritative location of the adagents.json file", + "properties": { + "$schema": { + "type": "string", + "description": "JSON Schema identifier for this adagents.json file" + }, + "authoritative_location": { + "type": "string", + "format": "uri", + "pattern": "^https://", + "description": "HTTPS URL of the authoritative adagents.json file. When present, this file is a reference and the authoritative location contains the actual agent authorization data." + }, + "last_updated": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp indicating when this reference was last updated" + } + }, + "required": [ + "authoritative_location" + ], + "additionalProperties": true + }, + { + "type": "object", + "description": "Inline structure variant - contains full agent authorization data", + "properties": { + "$schema": { + "type": "string", + "description": "JSON Schema identifier for this adagents.json file" + }, + "contact": { + "type": "object", + "description": "Contact information for the entity managing this adagents.json file (may be publisher or third-party operator)", + "properties": { + "name": { + "type": "string", + "description": "Name of the entity managing this file (e.g., 'Meta Advertising Operations', 'Clear Channel Digital')", + "minLength": 1, + "maxLength": 255 + }, + "email": { + "type": "string", + "format": "email", + "description": "Contact email for questions or issues with this authorization file", + "minLength": 1, + "maxLength": 255 + }, + "domain": { + "type": "string", + "description": "Primary domain of the entity managing this file", + "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$" + }, + "seller_id": { + "type": "string", + "description": "Seller ID from IAB Tech Lab sellers.json (if applicable)", + "minLength": 1, + "maxLength": 255 + }, + "tag_id": { + "type": "string", + "description": "TAG Certified Against Fraud ID for verification (if applicable)", + "minLength": 1, + "maxLength": 100 + }, + "privacy_policy_url": { + "type": "string", + "format": "uri", + "description": "URL to the entity's privacy policy. Used for consumer consent flows when interacting with this sales agent." + } + }, + "required": [ + "name" + ], + "additionalProperties": true + }, + "properties": { + "type": "array", + "description": "Array of all properties covered by this adagents.json file. Defines the canonical property list that authorized agents reference.", + "items": { + "$ref": "/schemas/3.0.0-beta.4/core/property.json" + }, + "minItems": 1 + }, + "tags": { + "type": "object", + "description": "Metadata for each tag referenced by properties. Provides human-readable context for property tag values.", + "additionalProperties": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Human-readable name for this tag" + }, + "description": { + "type": "string", + "description": "Description of what this tag represents" + } + }, + "required": [ + "name", + "description" + ], + "additionalProperties": true + } + }, + "authorized_agents": { + "type": "array", + "description": "Array of sales agents authorized to sell inventory for properties in this file", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The authorized agent's API endpoint URL" + }, + "authorized_for": { + "type": "string", + "description": "Human-readable description of what this agent is authorized to sell", + "minLength": 1, + "maxLength": 500 + }, + "authorization_type": { + "type": "string", + "const": "property_ids", + "description": "Discriminator indicating authorization by specific property IDs" + }, + "property_ids": { + "type": "array", + "description": "Property IDs this agent is authorized for. Resolved against the top-level properties array in this file", + "items": { + "$ref": "/schemas/3.0.0-beta.4/core/property-id.json" + }, + "minItems": 1 + } + }, + "required": [ + "url", + "authorized_for", + "authorization_type", + "property_ids" + ], + "additionalProperties": true + }, + { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The authorized agent's API endpoint URL" + }, + "authorized_for": { + "type": "string", + "description": "Human-readable description of what this agent is authorized to sell", + "minLength": 1, + "maxLength": 500 + }, + "authorization_type": { + "type": "string", + "const": "property_tags", + "description": "Discriminator indicating authorization by property tags" + }, + "property_tags": { + "type": "array", + "description": "Tags identifying which properties this agent is authorized for. Resolved against the top-level properties array in this file using tag matching", + "items": { + "$ref": "/schemas/3.0.0-beta.4/core/property-tag.json" + }, + "minItems": 1 + } + }, + "required": [ + "url", + "authorized_for", + "authorization_type", + "property_tags" + ], + "additionalProperties": true + }, + { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The authorized agent's API endpoint URL" + }, + "authorized_for": { + "type": "string", + "description": "Human-readable description of what this agent is authorized to sell", + "minLength": 1, + "maxLength": 500 + }, + "authorization_type": { + "type": "string", + "const": "inline_properties", + "description": "Discriminator indicating authorization by inline property definitions" + }, + "properties": { + "type": "array", + "description": "Specific properties this agent is authorized for (alternative to property_ids/property_tags)", + "items": { + "$ref": "/schemas/3.0.0-beta.4/core/property.json" + }, + "minItems": 1 + } + }, + "required": [ + "url", + "authorized_for", + "authorization_type", + "properties" + ], + "additionalProperties": true + }, + { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The authorized agent's API endpoint URL" + }, + "authorized_for": { + "type": "string", + "description": "Human-readable description of what this agent is authorized to sell", + "minLength": 1, + "maxLength": 500 + }, + "authorization_type": { + "type": "string", + "const": "publisher_properties", + "description": "Discriminator indicating authorization for properties from other publisher domains" + }, + "publisher_properties": { + "type": "array", + "description": "Properties from other publisher domains this agent is authorized for. Each entry specifies a publisher domain and which of their properties this agent can sell", + "items": { + "$ref": "/schemas/3.0.0-beta.4/core/publisher-property-selector.json" + }, + "minItems": 1 + } + }, + "required": [ + "url", + "authorized_for", + "authorization_type", + "publisher_properties" + ], + "additionalProperties": true + }, + { + "type": "object", + "description": "Authorization for signals by specific signal IDs", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The authorized signals agent's API endpoint URL" + }, + "authorized_for": { + "type": "string", + "description": "Human-readable description of what signals this agent is authorized to resell", + "minLength": 1, + "maxLength": 500 + }, + "authorization_type": { + "type": "string", + "const": "signal_ids", + "description": "Discriminator indicating authorization by specific signal IDs" + }, + "signal_ids": { + "type": "array", + "description": "Signal IDs this agent is authorized to resell. Resolved against the top-level signals array in this file", + "items": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$" + }, + "minItems": 1 + } + }, + "required": [ + "url", + "authorized_for", + "authorization_type", + "signal_ids" + ], + "additionalProperties": true + }, + { + "type": "object", + "description": "Authorization for signals by tag membership", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The authorized signals agent's API endpoint URL" + }, + "authorized_for": { + "type": "string", + "description": "Human-readable description of what signals this agent is authorized to resell", + "minLength": 1, + "maxLength": 500 + }, + "authorization_type": { + "type": "string", + "const": "signal_tags", + "description": "Discriminator indicating authorization by signal tags" + }, + "signal_tags": { + "type": "array", + "description": "Signal tags this agent is authorized for. Agent can resell all signals with these tags", + "items": { + "type": "string", + "pattern": "^[a-z0-9_-]+$" + }, + "minItems": 1 + } + }, + "required": [ + "url", + "authorized_for", + "authorization_type", + "signal_tags" + ], + "additionalProperties": true + } + ] + }, + "minItems": 1 + }, + "last_updated": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp indicating when this file was last updated" + }, + "property_features": { + "type": "array", + "description": "[AdCP 3.0] Optional list of agents that provide property feature data (certifications, scores, compliance status). Used for discovery - actual data comes from querying the agent's get_property_features task.", + "items": { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "The agent's API endpoint URL" + }, + "name": { + "type": "string", + "description": "Human-readable name of the vendor/agent (e.g., 'Scope3', 'TAG', 'OneTrust')" + }, + "features": { + "type": "array", + "description": "Feature IDs this agent provides (e.g., 'carbon_score', 'tag_certified_against_fraud'). Use get_adcp_capabilities on the agent for full definitions.", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "publisher_id": { + "type": "string", + "description": "Optional publisher identifier at this agent (for lookup)" + } + }, + "required": ["url", "name", "features"], + "additionalProperties": true + } + }, + "signals": { + "type": "array", + "description": "Signal catalog published by this data provider. Signals agents reference these signals via data_provider_domain + signal_id.", + "items": { + "$ref": "/schemas/3.0.0-beta.4/core/signal-definition.json" + }, + "minItems": 1 + }, + "signal_tags": { + "type": "object", + "description": "Metadata for each tag referenced by signals. Provides human-readable context for signal tag values.", + "additionalProperties": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Human-readable name for this tag" + }, + "description": { + "type": "string", + "description": "Description of what this tag represents" + } + }, + "required": [ + "name", + "description" + ], + "additionalProperties": true + } + } + }, + "required": [ + "authorized_agents" + ], + "additionalProperties": true + } + ], + "examples": [ + { + "$schema": "/schemas/3.0.0-beta.4/adagents.json", + "authoritative_location": "https://cdn.example.com/adagents/v2/adagents.json", + "last_updated": "2025-01-15T10:00:00Z" + }, + { + "$schema": "/schemas/3.0.0-beta.4/adagents.json", + "properties": [ + { + "property_type": "website", + "name": "Example Site", + "identifiers": [ + { + "type": "domain", + "value": "example.com" + } + ], + "publisher_domain": "example.com" + } + ], + "authorized_agents": [ + { + "url": "https://agent.example.com", + "authorized_for": "Official sales agent", + "authorization_type": "property_tags", + "property_tags": [ + "all" + ] + } + ], + "tags": { + "all": { + "name": "All Properties", + "description": "All properties in this file" + } + }, + "last_updated": "2025-01-10T12:00:00Z" + }, + { + "$schema": "/schemas/3.0.0-beta.4/adagents.json", + "contact": { + "name": "Meta Advertising Operations", + "email": "adops@meta.com", + "domain": "meta.com", + "seller_id": "pub-meta-12345", + "tag_id": "12345", + "privacy_policy_url": "https://www.meta.com/privacy/policy" + }, + "properties": [ + { + "property_type": "mobile_app", + "name": "Instagram", + "identifiers": [ + { + "type": "ios_bundle", + "value": "com.burbn.instagram" + }, + { + "type": "android_package", + "value": "com.instagram.android" + } + ], + "tags": [ + "meta_network", + "social_media" + ], + "supported_channels": ["social", "display", "olv"], + "publisher_domain": "instagram.com" + }, + { + "property_type": "mobile_app", + "name": "Facebook", + "identifiers": [ + { + "type": "ios_bundle", + "value": "com.facebook.Facebook" + }, + { + "type": "android_package", + "value": "com.facebook.katana" + } + ], + "tags": [ + "meta_network", + "social_media" + ], + "supported_channels": ["social", "display", "olv"], + "publisher_domain": "facebook.com" + }, + { + "property_type": "mobile_app", + "name": "WhatsApp", + "identifiers": [ + { + "type": "ios_bundle", + "value": "net.whatsapp.WhatsApp" + }, + { + "type": "android_package", + "value": "com.whatsapp" + } + ], + "tags": [ + "meta_network", + "messaging" + ], + "supported_channels": ["social", "display"], + "publisher_domain": "whatsapp.com" + } + ], + "tags": { + "meta_network": { + "name": "Meta Network", + "description": "All Meta-owned properties" + }, + "social_media": { + "name": "Social Media Apps", + "description": "Social networking applications" + }, + "messaging": { + "name": "Messaging Apps", + "description": "Messaging and communication apps" + } + }, + "authorized_agents": [ + { + "url": "https://meta-ads.com", + "authorized_for": "All Meta properties", + "authorization_type": "property_tags", + "property_tags": [ + "meta_network" + ] + } + ], + "last_updated": "2025-01-10T15:30:00Z" + }, + { + "$schema": "/schemas/3.0.0-beta.4/adagents.json", + "contact": { + "name": "Tumblr Advertising" + }, + "properties": [ + { + "property_type": "website", + "name": "Tumblr Corporate", + "identifiers": [ + { + "type": "domain", + "value": "tumblr.com" + } + ], + "tags": [ + "corporate" + ], + "publisher_domain": "tumblr.com" + } + ], + "tags": { + "corporate": { + "name": "Corporate Properties", + "description": "Tumblr-owned corporate properties (not user blogs)" + } + }, + "authorized_agents": [ + { + "url": "https://tumblr-sales.com", + "authorized_for": "Tumblr corporate properties only", + "authorization_type": "property_tags", + "property_tags": [ + "corporate" + ] + } + ], + "last_updated": "2025-01-10T16:00:00Z" + }, + { + "$schema": "/schemas/3.0.0-beta.4/adagents.json", + "contact": { + "name": "Example Third-Party Sales Agent", + "email": "sales@agent.example", + "domain": "agent.example" + }, + "authorized_agents": [ + { + "url": "https://agent.example/api", + "authorized_for": "CNN CTV properties via publisher authorization", + "authorization_type": "publisher_properties", + "publisher_properties": [ + { + "publisher_domain": "cnn.com", + "selection_type": "by_id", + "property_ids": [ + "cnn_ctv_app" + ] + } + ] + }, + { + "url": "https://agent.example/api", + "authorized_for": "All CTV properties from multiple publishers", + "authorization_type": "publisher_properties", + "publisher_properties": [ + { + "publisher_domain": "cnn.com", + "selection_type": "by_tag", + "property_tags": [ + "ctv" + ] + }, + { + "publisher_domain": "espn.com", + "selection_type": "by_tag", + "property_tags": [ + "ctv" + ] + } + ] + } + ], + "last_updated": "2025-01-10T17:00:00Z" + }, + { + "$schema": "/schemas/3.0.0-beta.4/adagents.json", + "contact": { + "name": "Premium News Publisher", + "email": "adops@news.example.com", + "domain": "news.example.com" + }, + "properties": [ + { + "property_type": "website", + "name": "News Example", + "identifiers": [ + { + "type": "domain", + "value": "news.example.com" + } + ], + "tags": ["premium", "news"], + "publisher_domain": "news.example.com" + } + ], + "tags": { + "premium": { + "name": "Premium Properties", + "description": "High-quality, brand-safe properties" + }, + "news": { + "name": "News Properties", + "description": "News and journalism content" + } + }, + "authorized_agents": [ + { + "url": "https://sales.news.example.com", + "authorized_for": "All news properties", + "authorization_type": "property_tags", + "property_tags": ["news"] + } + ], + "property_features": [ + { + "url": "https://api.scope3.com", + "name": "Scope3", + "features": ["carbon_score", "sustainability_grade"], + "publisher_id": "pub_news_12345" + }, + { + "url": "https://api.tagtoday.net", + "name": "TAG", + "features": ["tag_certified_against_fraud", "tag_brand_safety_certified"] + }, + { + "url": "https://api.onetrust.com", + "name": "OneTrust", + "features": ["gdpr_compliant", "tcf_registered", "ccpa_compliant"], + "publisher_id": "ot_news_67890" + } + ], + "last_updated": "2025-01-10T18:00:00Z" + }, + { + "$schema": "/schemas/3.0.0-beta.4/adagents.json", + "contact": { + "name": "Polk Automotive Data", + "email": "partnerships@polk.com", + "domain": "polk.com" + }, + "signals": [ + { + "id": "likely_tesla_buyers", + "name": "Likely Tesla Buyers", + "description": "Consumers modeled as likely to purchase a Tesla in the next 12 months based on vehicle registration, financial, and behavioral data", + "value_type": "binary", + "category": "purchase_intent", + "tags": ["automotive", "premium"] + }, + { + "id": "vehicle_ownership", + "name": "Current Vehicle Ownership", + "description": "Current vehicle make owned by the consumer", + "value_type": "categorical", + "category": "ownership", + "allowed_values": ["tesla", "bmw", "mercedes", "audi", "lexus", "other_luxury", "non_luxury"], + "tags": ["automotive"] + }, + { + "id": "purchase_propensity", + "name": "Auto Purchase Propensity", + "description": "Likelihood score of purchasing any new vehicle in the next 6 months", + "value_type": "numeric", + "category": "purchase_intent", + "range": { "min": 0, "max": 1, "unit": "score" }, + "tags": ["automotive"] + } + ], + "signal_tags": { + "automotive": { + "name": "Automotive Signals", + "description": "Vehicle-related audience segments" + }, + "premium": { + "name": "Premium Signals", + "description": "High-value premium audience segments" + } + }, + "authorized_agents": [ + { + "url": "https://liveramp.com/.well-known/adcp/signals", + "authorized_for": "All Polk automotive signals via LiveRamp", + "authorization_type": "signal_tags", + "signal_tags": ["automotive"] + }, + { + "url": "https://the-trade-desk.com/.well-known/adcp/signals", + "authorized_for": "Polk premium signals only", + "authorization_type": "signal_ids", + "signal_ids": ["likely_tesla_buyers"] + } + ], + "last_updated": "2025-01-15T10:00:00Z" + } + ] +} diff --git a/dist/schemas/3.0.0-beta.4/brand.json b/dist/schemas/3.0.0-beta.4/brand.json new file mode 100644 index 000000000..bea03b3aa --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/brand.json @@ -0,0 +1,722 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/brand.json", + "title": "Brand Discovery", + "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.", + "definitions": { + "domain": { + "type": "string", + "description": "A valid domain name", + "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$" + }, + "brand_id": { + "type": "string", + "description": "Brand identifier within the house portfolio. Lowercase alphanumeric with underscores. House chooses this ID.", + "pattern": "^[a-z0-9_]+$" + }, + "localized_name": { + "type": "object", + "description": "A localized name with language code key and name value", + "minProperties": 1, + "maxProperties": 1, + "additionalProperties": { + "type": "string", + "minLength": 1 + } + }, + "keller_type": { + "type": "string", + "enum": ["master", "sub_brand", "endorsed", "independent"], + "description": "Brand architecture type from Keller's theory. master: primary brand of house. sub_brand: carries parent name (Nike SB). endorsed: independent identity backed by parent (Air Jordan 'by Nike'). independent: operates separately (Converse under Nike, Inc.)" + }, + "logo": { + "type": "object", + "description": "Brand logo asset with structured fields for orientation, background compatibility, and variant type", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL to the logo asset" + }, + "orientation": { + "type": "string", + "enum": ["square", "horizontal", "vertical", "stacked"], + "description": "Logo aspect ratio orientation. square: ~1:1, horizontal: wide, vertical: tall, stacked: vertically arranged elements" + }, + "background": { + "type": "string", + "enum": ["dark-bg", "light-bg", "transparent-bg"], + "description": "Background compatibility. dark-bg: use on dark backgrounds, light-bg: use on light backgrounds, transparent-bg: has transparent background" + }, + "variant": { + "type": "string", + "enum": ["primary", "secondary", "icon", "wordmark", "full-lockup"], + "description": "Logo variant type. primary: main logo, secondary: alternative, icon: symbol only, wordmark: text only, full-lockup: complete logo" + }, + "tags": { + "type": "array", + "description": "Additional semantic tags for custom categorization beyond the standard orientation, background, and variant fields", + "items": { "type": "string" } + }, + "usage": { + "type": "string", + "description": "Human-readable description of when to use this logo variant (e.g., 'Primary logo for use on light backgrounds')" + }, + "width": { "type": "integer", "description": "Width in pixels" }, + "height": { "type": "integer", "description": "Height in pixels" } + }, + "required": ["url"], + "additionalProperties": true + }, + "color_value": { + "oneOf": [ + { "type": "string", "pattern": "^#[0-9A-Fa-f]{6}$" }, + { "type": "array", "items": { "type": "string", "pattern": "^#[0-9A-Fa-f]{6}$" }, "minItems": 1 } + ] + }, + "colors": { + "type": "object", + "description": "Brand color palette. Each role accepts a single hex color or an array of hex colors for brands with multiple values per role.", + "properties": { + "primary": { "$ref": "#/definitions/color_value" }, + "secondary": { "$ref": "#/definitions/color_value" }, + "accent": { "$ref": "#/definitions/color_value" }, + "background": { "$ref": "#/definitions/color_value" }, + "text": { "$ref": "#/definitions/color_value" } + }, + "additionalProperties": true + }, + "fonts": { + "type": "object", + "description": "Brand typography", + "properties": { + "primary": { "type": "string", "description": "Primary font family" }, + "secondary": { "type": "string", "description": "Secondary font family" }, + "font_urls": { + "type": "array", + "items": { "type": "string", "format": "uri" }, + "description": "URLs to web font files" + } + }, + "additionalProperties": true + }, + "asset": { + "type": "object", + "description": "Brand asset (image, video, audio, text)", + "properties": { + "asset_id": { "type": "string", "description": "Unique identifier" }, + "asset_type": { + "$ref": "/schemas/3.0.0-beta.4/enums/asset-content-type.json", + "description": "Type of asset content" + }, + "url": { "type": "string", "format": "uri", "description": "URL to CDN-hosted asset file" }, + "tags": { + "type": "array", + "items": { "type": "string" }, + "description": "Tags for discovery (e.g., 'hero', 'lifestyle', 'product', 'holiday')" + }, + "name": { "type": "string", "description": "Human-readable name" }, + "description": { "type": "string", "description": "Asset description or usage notes" }, + "width": { "type": "integer", "description": "Image/video width in pixels" }, + "height": { "type": "integer", "description": "Image/video height in pixels" }, + "duration_seconds": { "type": "number", "description": "Video/audio duration in seconds" }, + "file_size_bytes": { "type": "integer", "description": "File size in bytes" }, + "format": { "type": "string", "description": "File format (e.g., 'jpg', 'mp4', 'mp3')" }, + "metadata": { + "type": "object", + "description": "Additional asset-specific metadata", + "additionalProperties": true + } + }, + "required": ["asset_id", "asset_type", "url"], + "additionalProperties": true + }, + "property": { + "type": "object", + "description": "A digital property owned by a brand", + "properties": { + "type": { + "type": "string", + "enum": ["website", "mobile_app", "ctv_app", "desktop_app", "dooh", "podcast", "radio", "streaming_audio"], + "description": "Property type" + }, + "identifier": { + "type": "string", + "description": "Property identifier - domain for websites, bundle ID for apps", + "minLength": 1 + }, + "store": { + "type": "string", + "enum": ["apple", "google", "amazon", "roku", "samsung", "lg", "other"], + "description": "App store for mobile/CTV apps" + }, + "region": { + "type": "string", + "description": "ISO 3166-1 alpha-2 country code or 'global'", + "pattern": "^([A-Z]{2}|global)$" + }, + "primary": { + "type": "boolean", + "default": false, + "description": "Whether this is the primary property for the brand" + } + }, + "required": ["type", "identifier"], + "additionalProperties": true + }, + "product_catalog": { + "type": "object", + "description": "Product catalog for e-commerce brands", + "properties": { + "feed_url": { "type": "string", "format": "uri", "description": "URL to product catalog feed" }, + "feed_format": { + "type": "string", + "enum": ["google_merchant_center", "facebook_catalog", "openai_product_feed", "custom"], + "description": "Format of the product feed" + }, + "categories": { + "type": "array", + "items": { "type": "string" }, + "description": "Product categories available in the catalog" + }, + "last_updated": { + "type": "string", + "format": "date-time", + "description": "When the product catalog was last updated" + }, + "update_frequency": { + "type": "string", + "enum": ["realtime", "hourly", "daily", "weekly"], + "description": "How frequently the product catalog is updated" + }, + "agentic_checkout": { + "type": "object", + "description": "Agentic checkout endpoint configuration", + "properties": { + "endpoint": { "type": "string", "format": "uri", "description": "Base URL for checkout session API" }, + "spec": { "type": "string", "enum": ["openai_agentic_checkout_v1"], "description": "Checkout API specification" }, + "supported_payment_providers": { + "type": "array", + "description": "Payment providers supported by this checkout endpoint", + "items": { "type": "string" } + } + }, + "required": ["endpoint", "spec"] + } + }, + "required": ["feed_url"], + "additionalProperties": true + }, + "brand": { + "type": "object", + "description": "A brand within a house portfolio. Combines identity (who) with creative assets (how to represent). Referenced as domain + brand_id.", + "properties": { + "id": { + "$ref": "#/definitions/brand_id", + "description": "Brand identifier within the house. House chooses this ID." + }, + "url": { + "type": "string", + "format": "uri", + "description": "Primary brand URL for context and asset discovery" + }, + "names": { + "type": "array", + "description": "Localized brand names. Multiple entries per language allowed for aliases.", + "items": { "$ref": "#/definitions/localized_name" }, + "minItems": 1 + }, + "keller_type": { "$ref": "#/definitions/keller_type" }, + "parent_brand": { + "$ref": "#/definitions/brand_id", + "description": "Parent brand ID for sub-brands and endorsed brands" + }, + "description": { + "type": "string", + "description": "Brand description" + }, + "industry": { + "type": "string", + "description": "Industry or vertical (e.g., 'retail', 'automotive', 'cpg')" + }, + "target_audience": { + "type": "string", + "description": "Primary target audience" + }, + "logos": { + "type": "array", + "items": { "$ref": "#/definitions/logo" }, + "description": "Brand logo assets" + }, + "colors": { "$ref": "#/definitions/colors" }, + "fonts": { "$ref": "#/definitions/fonts" }, + "tone": { + "description": "Brand voice and messaging tone guidelines", + "oneOf": [ + { + "type": "string", + "description": "Simple tone descriptors for backwards compatibility" + }, + { + "type": "object", + "description": "Structured brand voice guidelines", + "properties": { + "voice": { "type": "string", "description": "High-level voice descriptor (e.g., 'warm and inviting', 'professional and trustworthy')" }, + "attributes": { + "type": "array", + "description": "Personality traits that characterize the brand voice", + "items": { "type": "string" } + }, + "dos": { + "type": "array", + "description": "Guidance for copy generation - what TO do", + "items": { "type": "string" } + }, + "donts": { + "type": "array", + "description": "Guardrails to avoid brand violations - what NOT to do", + "items": { "type": "string" } + } + } + } + ] + }, + "tagline": { + "type": "string", + "description": "Brand tagline or slogan" + }, + "assets": { + "type": "array", + "items": { "$ref": "#/definitions/asset" }, + "description": "Brand asset library" + }, + "properties": { + "type": "array", + "items": { "$ref": "#/definitions/property" }, + "description": "Digital properties owned by this brand" + }, + "product_catalog": { "$ref": "#/definitions/product_catalog" }, + "privacy_policy_url": { + "type": "string", + "format": "uri", + "description": "URL to the brand's privacy policy" + }, + "disclaimers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "text": { "type": "string" }, + "context": { "type": "string" }, + "required": { "type": "boolean", "default": true } + }, + "required": ["text"] + }, + "description": "Legal disclaimers for creatives" + }, + "voice": { + "type": "object", + "description": "TTS voice configuration", + "properties": { + "provider": { "type": "string" }, + "voice_id": { "type": "string" }, + "settings": { "type": "object", "additionalProperties": true } + }, + "additionalProperties": true + }, + "avatar": { + "type": "object", + "description": "Visual avatar configuration", + "properties": { + "provider": { "type": "string" }, + "avatar_id": { "type": "string" }, + "settings": { "type": "object", "additionalProperties": true } + }, + "additionalProperties": true + }, + "brand_agent": { + "$ref": "#/definitions/brand_agent", + "description": "Brand agent that provides dynamic brand data via MCP" + }, + "contact": { + "type": "object", + "description": "Brand-level contact information", + "properties": { + "email": { "type": "string", "format": "email", "description": "Contact email" }, + "phone": { "type": "string", "description": "Contact phone number" } + } + } + }, + "required": ["id", "names"], + "additionalProperties": true + }, + "house": { + "type": "object", + "description": "Corporate or organizational entity that owns brands", + "properties": { + "domain": { + "$ref": "#/definitions/domain", + "description": "The house's domain where brand.json is hosted" + }, + "name": { + "type": "string", + "description": "Primary display name of the house", + "minLength": 1 + }, + "names": { + "type": "array", + "description": "Localized house names including legal name, stock symbol, etc.", + "items": { "$ref": "#/definitions/localized_name" } + }, + "architecture": { + "type": "string", + "enum": ["branded_house", "house_of_brands", "hybrid"], + "description": "Brand architecture model: branded_house (Google), house_of_brands (P&G), hybrid (Nike)" + } + }, + "required": ["domain", "name"], + "additionalProperties": true + }, + "brand_agent": { + "type": "object", + "description": "Reference to a brand agent that provides brand data via MCP", + "properties": { + "url": { + "type": "string", + "format": "uri", + "pattern": "^https://", + "description": "Brand agent MCP endpoint URL" + }, + "id": { + "type": "string", + "description": "Agent identifier (useful for logging, multi-tenant DAMs)", + "pattern": "^[a-z0-9_]+$" + } + }, + "required": ["url", "id"], + "additionalProperties": true + }, + "authorized_operator": { + "type": "object", + "description": "An entity authorized to represent brands from this house. Verified by resolving the operator's domain.", + "properties": { + "domain": { + "$ref": "#/definitions/domain", + "description": "Domain of the authorized operator (e.g., 'groupm.com')" + }, + "brands": { + "type": "array", + "description": "Brand IDs this operator is authorized for. Use ['*'] for all brands in the portfolio.", + "items": { + "type": "string", + "pattern": "^([a-z0-9_]+|\\*)$" + }, + "minItems": 1 + }, + "countries": { + "type": "array", + "description": "ISO 3166-1 alpha-2 country codes where this authorization applies. Omit for global authorization.", + "items": { + "type": "string", + "pattern": "^[A-Z]{2}$" + } + } + }, + "required": ["domain", "brands"], + "additionalProperties": true + }, + "contact": { + "type": "object", + "description": "Contact information", + "properties": { + "name": { "type": "string", "minLength": 1, "maxLength": 255 }, + "email": { "type": "string", "format": "email", "maxLength": 255 }, + "domain": { "$ref": "#/definitions/domain" } + }, + "required": ["name"], + "additionalProperties": true + } + }, + "oneOf": [ + { + "type": "object", + "title": "Authoritative Location Redirect", + "description": "Redirects to a hosted brand.json file at another URL", + "properties": { + "$schema": { "type": "string" }, + "authoritative_location": { + "type": "string", + "format": "uri", + "pattern": "^https://", + "description": "HTTPS URL of the authoritative brand.json file" + }, + "last_updated": { "type": "string", "format": "date-time" } + }, + "required": ["authoritative_location"], + "additionalProperties": false + }, + { + "type": "object", + "title": "House Redirect", + "description": "Redirects to the house domain that contains the full brand portfolio", + "properties": { + "$schema": { "type": "string" }, + "house": { + "$ref": "#/definitions/domain", + "description": "House domain to fetch brand portfolio from" + }, + "region": { + "type": "string", + "pattern": "^[A-Z]{2}$", + "description": "ISO 3166-1 alpha-2 country code if this is a regional domain" + }, + "note": { "type": "string" }, + "last_updated": { "type": "string", "format": "date-time" } + }, + "required": ["house"], + "additionalProperties": false + }, + { + "type": "object", + "title": "Brand Agent", + "description": "Brand with an agent that provides brand info via MCP", + "properties": { + "$schema": { "type": "string" }, + "version": { "type": "string" }, + "brand_agent": { "$ref": "#/definitions/brand_agent" }, + "contact": { "$ref": "#/definitions/contact" }, + "last_updated": { "type": "string", "format": "date-time" } + }, + "required": ["brand_agent"], + "additionalProperties": false + }, + { + "type": "object", + "title": "House Portfolio", + "description": "Full house/brand portfolio with hierarchy, creative assets, and properties", + "properties": { + "$schema": { "type": "string" }, + "version": { "type": "string" }, + "house": { "$ref": "#/definitions/house" }, + "brands": { + "type": "array", + "description": "Brands owned by this house", + "items": { "$ref": "#/definitions/brand" }, + "minItems": 1 + }, + "contact": { "$ref": "#/definitions/contact" }, + "authorized_operators": { + "type": "array", + "description": "Entities authorized to represent brands from this house. Third parties (sellers, platforms) can verify an operator's authorization by checking this list. Operators are identified by domain.", + "items": { "$ref": "#/definitions/authorized_operator" } + }, + "trademarks": { + "type": "array", + "items": { + "type": "object", + "properties": { + "registry": { "type": "string" }, + "number": { "type": "string" }, + "mark": { "type": "string" } + }, + "required": ["registry", "number", "mark"], + "additionalProperties": true + } + }, + "last_updated": { "type": "string", "format": "date-time" } + }, + "required": ["house", "brands"], + "additionalProperties": false + } + ], + "examples": [ + { + "$schema": "/schemas/3.0.0-beta.4/brand.json", + "authoritative_location": "https://adcontextprotocol.org/brand/abc123/brand.json" + }, + { + "$schema": "/schemas/3.0.0-beta.4/brand.json", + "house": "nikeinc.com", + "note": "Redirect to house domain for full brand portfolio" + }, + { + "$schema": "/schemas/3.0.0-beta.4/brand.json", + "version": "1.0", + "brand_agent": { + "url": "https://agent.acme.com/mcp", + "id": "acme_brand_agent" + } + }, + { + "$schema": "/schemas/3.0.0-beta.4/brand.json", + "version": "1.0", + "house": { + "domain": "pg.com", + "name": "Procter & Gamble", + "architecture": "house_of_brands" + }, + "brands": [ + { + "id": "tide", + "url": "https://tide.com", + "names": [{"en": "Tide"}, {"es": "Tide"}, {"zh": "汰渍"}], + "keller_type": "master", + "industry": "cpg", + "description": "Laundry detergent brand", + "logos": [ + { + "url": "https://cdn.pg.com/tide/logo-square.png", + "orientation": "square", + "background": "transparent-bg", + "variant": "primary", + "usage": "Primary logo for general use" + }, + { + "url": "https://cdn.pg.com/tide/logo-horizontal-dark.png", + "orientation": "horizontal", + "background": "dark-bg", + "variant": "full-lockup", + "usage": "Full lockup for dark backgrounds" + } + ], + "colors": {"primary": "#FF6600", "secondary": "#0066CC"}, + "tone": { + "voice": "clean, fresh, trustworthy", + "attributes": ["reliable", "family-friendly", "confident"], + "dos": ["Use simple, direct language", "Emphasize cleaning power"], + "donts": ["Avoid technical jargon", "Don't be overly serious"] + }, + "tagline": "Tide's In, Dirt's Out", + "properties": [ + {"type": "website", "identifier": "tide.com", "primary": true}, + {"type": "mobile_app", "store": "apple", "identifier": "com.pg.tide"} + ], + "contact": { + "email": "brands@pg.com" + } + }, + { + "id": "pampers", + "url": "https://pampers.com", + "names": [{"en": "Pampers"}], + "keller_type": "master", + "industry": "cpg", + "logos": [ + { + "url": "https://cdn.pg.com/pampers/logo.png", + "orientation": "horizontal", + "variant": "primary" + } + ], + "colors": {"primary": "#00A0D2"}, + "properties": [ + {"type": "website", "identifier": "pampers.com", "primary": true} + ] + } + ], + "contact": { + "name": "P&G Brand Team", + "email": "brands@pg.com" + }, + "last_updated": "2026-01-15T10:00:00Z" + }, + { + "$schema": "/schemas/3.0.0-beta.4/brand.json", + "version": "1.0", + "house": { + "domain": "nikeinc.com", + "name": "Nike, Inc.", + "architecture": "hybrid" + }, + "brands": [ + { + "id": "nike", + "url": "https://nike.com", + "names": [{"en": "Nike"}, {"zh": "耐克"}, {"ja": "ナイキ"}], + "keller_type": "master", + "logos": [ + { + "url": "https://cdn.nike.com/swoosh-dark.svg", + "orientation": "horizontal", + "background": "dark-bg", + "variant": "icon", + "usage": "Swoosh icon for dark backgrounds" + }, + { + "url": "https://cdn.nike.com/logo-full.svg", + "orientation": "horizontal", + "background": "light-bg", + "variant": "full-lockup", + "usage": "Full logo with wordmark for light backgrounds" + } + ], + "colors": {"primary": "#111111", "accent": "#FF6600"}, + "tone": "inspirational, bold, athletic", + "tagline": "Just Do It", + "properties": [ + {"type": "website", "identifier": "nike.com", "primary": true}, + {"type": "website", "identifier": "nike.cn", "region": "CN"}, + {"type": "mobile_app", "store": "apple", "identifier": "com.nike.omega"} + ] + }, + { + "id": "air_jordan", + "url": "https://jordan.com", + "names": [{"en": "Air Jordan"}, {"en": "Jordan"}, {"en": "Jumpman"}], + "keller_type": "endorsed", + "parent_brand": "nike", + "logos": [ + { + "url": "https://cdn.nike.com/jumpman.svg", + "orientation": "square", + "background": "transparent-bg", + "variant": "icon" + } + ], + "colors": {"primary": "#CE1141", "secondary": "#111111"}, + "properties": [ + {"type": "website", "identifier": "jordan.com", "primary": true}, + {"type": "website", "identifier": "jumpman23.com"} + ], + "brand_agent": { + "url": "https://dam.nike.com/mcp", + "id": "nike_dam" + } + }, + { + "id": "converse", + "url": "https://converse.com", + "names": [{"en": "Converse"}], + "keller_type": "independent", + "logos": [ + { + "url": "https://cdn.converse.com/star.svg", + "orientation": "square", + "variant": "icon" + } + ], + "properties": [ + {"type": "website", "identifier": "converse.com", "primary": true} + ] + } + ], + "authorized_operators": [ + { + "domain": "wpp.com", + "brands": ["nike", "air_jordan"], + "countries": ["US", "GB", "DE", "FR"] + }, + { + "domain": "dentsu.co.jp", + "brands": ["nike"], + "countries": ["JP"] + }, + { + "domain": "nike.com", + "brands": ["*"] + } + ], + "last_updated": "2026-01-15T10:00:00Z" + } + ] +} diff --git a/dist/schemas/3.0.0-beta.4/bundled/content-standards/calibrate-content-request.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/calibrate-content-request.json new file mode 100644 index 000000000..d138eb540 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/calibrate-content-request.json @@ -0,0 +1,456 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/calibrate-content-request.json", + "title": "Calibrate Content Request", + "description": "Request parameters for evaluating content during calibration. Multi-turn dialogue is handled at the protocol layer via contextId.", + "type": "object", + "properties": { + "standards_id": { + "type": "string", + "description": "Standards configuration to calibrate against" + }, + "artifact": { + "title": "Artifact", + "description": "Artifact to evaluate", + "type": "object", + "properties": { + "property_id": { + "title": "Identifier", + "description": "Identifier for the property where this artifact appears", + "type": "object", + "properties": { + "type": { + "title": "Property Identifier Types", + "description": "Type of identifier", + "type": "string", + "enum": [ + "domain", + "subdomain", + "network_id", + "ios_bundle", + "android_package", + "apple_app_store_id", + "google_play_id", + "roku_store_id", + "fire_tv_asin", + "samsung_app_id", + "apple_tv_bundle", + "bundle_id", + "venue_id", + "screen_id", + "openooh_venue_type", + "rss_url", + "apple_podcast_id", + "spotify_show_id", + "podcast_guid" + ], + "examples": [ + "domain", + "ios_bundle", + "venue_id", + "apple_podcast_id" + ] + }, + "value": { + "type": "string", + "description": "The identifier value. For domain type: 'example.com' matches base domain plus www and m subdomains; 'edition.example.com' matches that specific subdomain; '*.example.com' matches ALL subdomains but NOT base domain" + } + }, + "required": [ + "type", + "value" + ], + "additionalProperties": false + }, + "artifact_id": { + "type": "string", + "description": "Identifier for this artifact within the property. The property owner defines the scheme (e.g., 'article_12345', 'episode_42_segment_3', 'post_abc123')." + }, + "variant_id": { + "type": "string", + "description": "Identifies a specific variant of this artifact. Use for A/B tests, translations, or temporal versions. Examples: 'en', 'es-MX', 'v2', 'headline_test_b'. The combination of artifact_id + variant_id must be unique." + }, + "format_id": { + "title": "Format ID", + "description": "Optional reference to a format definition. Uses the same format registry as creative formats.", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "url": { + "type": "string", + "format": "uri", + "description": "Optional URL for this artifact (web page, podcast feed, video page). Not all artifacts have URLs (e.g., Instagram content, podcast segments, TV scenes)." + }, + "published_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was published (ISO 8601 format)" + }, + "last_update_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was last modified (ISO 8601 format)" + }, + "assets": { + "type": "array", + "description": "Artifact assets in document flow order - text blocks, images, video, audio", + "items": { + "oneOf": [ + { + "type": "object", + "description": "Text block (paragraph, heading, etc.)", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "role": { + "type": "string", + "enum": [ + "title", + "paragraph", + "heading", + "caption", + "quote", + "list_item", + "description" + ], + "description": "Role of this text in the document. Use 'title' for the main artifact title, 'description' for summaries." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for this text (e.g., 'en', 'es-MX'). Useful when artifact contains mixed-language content." + }, + "heading_level": { + "type": "integer", + "minimum": 1, + "maximum": 6, + "description": "Heading level (1-6), only for role=heading" + } + }, + "required": [ + "type", + "content" + ] + }, + { + "type": "object", + "description": "Image asset", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Image URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "alt_text": { + "type": "string", + "description": "Alt text or image description" + }, + "caption": { + "type": "string", + "description": "Image caption" + }, + "width": { + "type": "integer", + "description": "Image width in pixels" + }, + "height": { + "type": "integer", + "description": "Image height in pixels" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Video asset", + "properties": { + "type": { + "type": "string", + "const": "video" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Video URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Video duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Video transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "subtitles", + "closed_captions", + "dub", + "generated" + ], + "description": "How the transcript was generated" + }, + "thumbnail_url": { + "type": "string", + "format": "uri", + "description": "Video thumbnail URL" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Audio asset", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Audio URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Audio duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Audio transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "closed_captions", + "generated" + ], + "description": "How the transcript was generated" + } + }, + "required": [ + "type", + "url" + ] + } + ] + } + }, + "metadata": { + "type": "object", + "description": "Rich metadata extracted from the artifact", + "properties": { + "canonical": { + "type": "string", + "format": "uri", + "description": "Canonical URL" + }, + "author": { + "type": "string", + "description": "Artifact author name" + }, + "keywords": { + "type": "string", + "description": "Artifact keywords" + }, + "open_graph": { + "type": "object", + "description": "Open Graph protocol metadata", + "additionalProperties": true + }, + "twitter_card": { + "type": "object", + "description": "Twitter Card metadata", + "additionalProperties": true + }, + "json_ld": { + "type": "array", + "description": "JSON-LD structured data (schema.org)", + "items": { + "type": "object" + } + } + }, + "additionalProperties": true + }, + "identifiers": { + "type": "object", + "description": "Platform-specific identifiers for this artifact", + "properties": { + "apple_podcast_id": { + "type": "string", + "description": "Apple Podcasts ID" + }, + "spotify_show_id": { + "type": "string", + "description": "Spotify show ID" + }, + "podcast_guid": { + "type": "string", + "description": "Podcast GUID (from RSS feed)" + }, + "youtube_video_id": { + "type": "string", + "description": "YouTube video ID" + }, + "rss_url": { + "type": "string", + "format": "uri", + "description": "RSS feed URL" + } + }, + "additionalProperties": true + } + }, + "required": [ + "property_id", + "artifact_id", + "assets" + ], + "additionalProperties": true, + "$defs": { + "asset_access": { + "type": "object", + "description": "Authentication for accessing secured asset URLs", + "oneOf": [ + { + "type": "object", + "description": "Bearer token authentication", + "properties": { + "method": { + "type": "string", + "const": "bearer_token" + }, + "token": { + "type": "string", + "description": "OAuth2 bearer token for Authorization header" + } + }, + "required": [ + "method", + "token" + ] + }, + { + "type": "object", + "description": "Service account authentication (GCP, AWS)", + "properties": { + "method": { + "type": "string", + "const": "service_account" + }, + "provider": { + "type": "string", + "enum": [ + "gcp", + "aws" + ], + "description": "Cloud provider" + }, + "credentials": { + "type": "object", + "description": "Service account credentials", + "additionalProperties": true + } + }, + "required": [ + "method", + "provider" + ] + }, + { + "type": "object", + "description": "Pre-signed URL (credentials embedded in URL)", + "properties": { + "method": { + "type": "string", + "const": "signed_url" + } + }, + "required": [ + "method" + ] + } + ] + } + } + } + }, + "required": [ + "standards_id", + "artifact" + ], + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.773Z", + "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." + } +} \ No newline at end of file diff --git a/dist/schemas/3.0.0-beta.4/bundled/content-standards/calibrate-content-response.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/calibrate-content-response.json new file mode 100644 index 000000000..e3edbf868 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/calibrate-content-response.json @@ -0,0 +1,129 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/calibrate-content-response.json", + "title": "Calibrate Content Response", + "description": "Response payload with verdict and detailed explanations for collaborative calibration", + "type": "object", + "oneOf": [ + { + "type": "object", + "description": "Success response with detailed calibration feedback", + "properties": { + "verdict": { + "type": "string", + "enum": [ + "pass", + "fail" + ], + "description": "Overall pass/fail verdict for the content evaluation" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Model confidence in the verdict (0-1)" + }, + "explanation": { + "type": "string", + "description": "Detailed natural language explanation of the decision" + }, + "features": { + "type": "array", + "description": "Per-feature breakdown with explanations", + "items": { + "type": "object", + "properties": { + "feature_id": { + "type": "string", + "description": "Which feature was evaluated (e.g., brand_safety, brand_suitability, competitor_adjacency)" + }, + "status": { + "type": "string", + "enum": [ + "passed", + "failed", + "warning", + "unevaluated" + ], + "description": "Evaluation status for this feature" + }, + "explanation": { + "type": "string", + "description": "Human-readable explanation of why this feature passed or failed" + } + }, + "required": [ + "feature_id", + "status" + ] + } + }, + "errors": { + "not": {}, + "description": "Field must not be present in success response" + } + }, + "required": [ + "verdict" + ] + }, + { + "type": "object", + "description": "Error response", + "properties": { + "errors": { + "type": "array", + "items": { + "title": "Error", + "description": "Standard error structure for task-specific errors and warnings", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Error code for programmatic handling" + }, + "message": { + "type": "string", + "description": "Human-readable error message" + }, + "field": { + "type": "string", + "description": "Field path associated with the error (e.g., 'packages[0].targeting')" + }, + "suggestion": { + "type": "string", + "description": "Suggested fix for the error" + }, + "retry_after": { + "type": "number", + "description": "Seconds to wait before retrying the operation", + "minimum": 0 + }, + "details": { + "type": "object", + "description": "Additional task-specific error details", + "additionalProperties": true + } + }, + "required": [ + "code", + "message" + ], + "additionalProperties": true + } + }, + "verdict": { + "not": {}, + "description": "Field must not be present in error response" + } + }, + "required": [ + "errors" + ] + } + ], + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.773Z", + "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." + } +} \ No newline at end of file diff --git a/dist/schemas/3.0.0-beta.4/bundled/content-standards/create-content-standards-request.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/create-content-standards-request.json new file mode 100644 index 000000000..232f1b0f1 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/create-content-standards-request.json @@ -0,0 +1,1055 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/create-content-standards-request.json", + "title": "Create Content Standards Request", + "description": "Request parameters for creating a new content standards configuration", + "type": "object", + "properties": { + "scope": { + "type": "object", + "description": "Where this standards configuration applies", + "properties": { + "countries_all": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "ISO 3166-1 alpha-2 country codes. Standards apply in ALL listed countries (AND logic)." + }, + "channels_any": { + "type": "array", + "items": { + "title": "Media Channel", + "description": "Standardized advertising media channels describing how buyers allocate budget. Channels are planning abstractions, not technical substrates. See the Media Channel Taxonomy specification for detailed definitions.", + "type": "string", + "enum": [ + "display", + "olv", + "social", + "search", + "ctv", + "linear_tv", + "radio", + "streaming_audio", + "podcast", + "dooh", + "ooh", + "print", + "cinema", + "email", + "gaming", + "retail_media", + "influencer", + "affiliate", + "product_placement" + ], + "enumDescriptions": { + "display": "Digital display advertising (banners, native, rich media) across web and app", + "olv": "Online video advertising outside CTV (pre-roll, outstream, in-app video)", + "social": "Social media platforms (Facebook, Instagram, TikTok, LinkedIn, etc.)", + "search": "Search engine advertising and search networks", + "ctv": "Connected TV and streaming on television screens", + "linear_tv": "Traditional broadcast and cable television", + "radio": "Traditional AM/FM radio broadcast", + "streaming_audio": "Digital audio streaming services (Spotify, Pandora, etc.)", + "podcast": "Podcast advertising (host-read or dynamically inserted)", + "dooh": "Digital out-of-home screens in public spaces", + "ooh": "Classic out-of-home (physical billboards, transit, etc.)", + "print": "Newspapers, magazines, and other print publications", + "cinema": "Movie theater advertising", + "email": "Email advertising and sponsored newsletter content", + "gaming": "In-game advertising across platforms", + "retail_media": "Retail media networks and commerce marketplaces (Amazon, Walmart, Instacart)", + "influencer": "Creator and influencer marketing partnerships", + "affiliate": "Affiliate networks, comparison sites, and performance-based partnerships", + "product_placement": "Product placement, branded content, and sponsorship integrations" + } + }, + "minItems": 1, + "description": "Advertising channels. Standards apply to ANY of the listed channels (OR logic)." + }, + "languages_any": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "BCP 47 language tags (e.g., 'en', 'de', 'fr'). Standards apply to content in ANY of these languages (OR logic). Content in unlisted languages is not covered by these standards." + }, + "description": { + "type": "string", + "description": "Human-readable description of this scope" + } + }, + "required": [ + "languages_any" + ] + }, + "policy": { + "type": "string", + "description": "Natural language policy describing acceptable and unacceptable content contexts. Used by LLMs and human reviewers to make judgments." + }, + "calibration_exemplars": { + "type": "object", + "description": "Training/test set to calibrate policy interpretation. Use URL references for pages to be fetched and analyzed, or full artifacts for pre-extracted content.", + "properties": { + "pass": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "description": "URL reference - specific page to fetch and evaluate", + "properties": { + "type": { + "type": "string", + "const": "url", + "description": "Indicates this is a URL reference" + }, + "value": { + "type": "string", + "format": "uri", + "description": "Full URL to a specific page (e.g., 'https://espn.com/nba/story/_/id/12345/lakers-win')" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for content at this URL" + } + }, + "required": [ + "type", + "value" + ] + }, + { + "title": "Artifact", + "description": "Full artifact with pre-extracted content (text, images, video, audio)", + "type": "object", + "properties": { + "property_id": { + "title": "Identifier", + "description": "Identifier for the property where this artifact appears", + "type": "object", + "properties": { + "type": { + "title": "Property Identifier Types", + "description": "Type of identifier", + "type": "string", + "enum": [ + "domain", + "subdomain", + "network_id", + "ios_bundle", + "android_package", + "apple_app_store_id", + "google_play_id", + "roku_store_id", + "fire_tv_asin", + "samsung_app_id", + "apple_tv_bundle", + "bundle_id", + "venue_id", + "screen_id", + "openooh_venue_type", + "rss_url", + "apple_podcast_id", + "spotify_show_id", + "podcast_guid" + ], + "examples": [ + "domain", + "ios_bundle", + "venue_id", + "apple_podcast_id" + ] + }, + "value": { + "type": "string", + "description": "The identifier value. For domain type: 'example.com' matches base domain plus www and m subdomains; 'edition.example.com' matches that specific subdomain; '*.example.com' matches ALL subdomains but NOT base domain" + } + }, + "required": [ + "type", + "value" + ], + "additionalProperties": false + }, + "artifact_id": { + "type": "string", + "description": "Identifier for this artifact within the property. The property owner defines the scheme (e.g., 'article_12345', 'episode_42_segment_3', 'post_abc123')." + }, + "variant_id": { + "type": "string", + "description": "Identifies a specific variant of this artifact. Use for A/B tests, translations, or temporal versions. Examples: 'en', 'es-MX', 'v2', 'headline_test_b'. The combination of artifact_id + variant_id must be unique." + }, + "format_id": { + "title": "Format ID", + "description": "Optional reference to a format definition. Uses the same format registry as creative formats.", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "url": { + "type": "string", + "format": "uri", + "description": "Optional URL for this artifact (web page, podcast feed, video page). Not all artifacts have URLs (e.g., Instagram content, podcast segments, TV scenes)." + }, + "published_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was published (ISO 8601 format)" + }, + "last_update_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was last modified (ISO 8601 format)" + }, + "assets": { + "type": "array", + "description": "Artifact assets in document flow order - text blocks, images, video, audio", + "items": { + "oneOf": [ + { + "type": "object", + "description": "Text block (paragraph, heading, etc.)", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "role": { + "type": "string", + "enum": [ + "title", + "paragraph", + "heading", + "caption", + "quote", + "list_item", + "description" + ], + "description": "Role of this text in the document. Use 'title' for the main artifact title, 'description' for summaries." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for this text (e.g., 'en', 'es-MX'). Useful when artifact contains mixed-language content." + }, + "heading_level": { + "type": "integer", + "minimum": 1, + "maximum": 6, + "description": "Heading level (1-6), only for role=heading" + } + }, + "required": [ + "type", + "content" + ] + }, + { + "type": "object", + "description": "Image asset", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Image URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "alt_text": { + "type": "string", + "description": "Alt text or image description" + }, + "caption": { + "type": "string", + "description": "Image caption" + }, + "width": { + "type": "integer", + "description": "Image width in pixels" + }, + "height": { + "type": "integer", + "description": "Image height in pixels" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Video asset", + "properties": { + "type": { + "type": "string", + "const": "video" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Video URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Video duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Video transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "subtitles", + "closed_captions", + "dub", + "generated" + ], + "description": "How the transcript was generated" + }, + "thumbnail_url": { + "type": "string", + "format": "uri", + "description": "Video thumbnail URL" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Audio asset", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Audio URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Audio duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Audio transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "closed_captions", + "generated" + ], + "description": "How the transcript was generated" + } + }, + "required": [ + "type", + "url" + ] + } + ] + } + }, + "metadata": { + "type": "object", + "description": "Rich metadata extracted from the artifact", + "properties": { + "canonical": { + "type": "string", + "format": "uri", + "description": "Canonical URL" + }, + "author": { + "type": "string", + "description": "Artifact author name" + }, + "keywords": { + "type": "string", + "description": "Artifact keywords" + }, + "open_graph": { + "type": "object", + "description": "Open Graph protocol metadata", + "additionalProperties": true + }, + "twitter_card": { + "type": "object", + "description": "Twitter Card metadata", + "additionalProperties": true + }, + "json_ld": { + "type": "array", + "description": "JSON-LD structured data (schema.org)", + "items": { + "type": "object" + } + } + }, + "additionalProperties": true + }, + "identifiers": { + "type": "object", + "description": "Platform-specific identifiers for this artifact", + "properties": { + "apple_podcast_id": { + "type": "string", + "description": "Apple Podcasts ID" + }, + "spotify_show_id": { + "type": "string", + "description": "Spotify show ID" + }, + "podcast_guid": { + "type": "string", + "description": "Podcast GUID (from RSS feed)" + }, + "youtube_video_id": { + "type": "string", + "description": "YouTube video ID" + }, + "rss_url": { + "type": "string", + "format": "uri", + "description": "RSS feed URL" + } + }, + "additionalProperties": true + } + }, + "required": [ + "property_id", + "artifact_id", + "assets" + ], + "additionalProperties": true, + "$defs": { + "asset_access": { + "type": "object", + "description": "Authentication for accessing secured asset URLs", + "oneOf": [ + { + "type": "object", + "description": "Bearer token authentication", + "properties": { + "method": { + "type": "string", + "const": "bearer_token" + }, + "token": { + "type": "string", + "description": "OAuth2 bearer token for Authorization header" + } + }, + "required": [ + "method", + "token" + ] + }, + { + "type": "object", + "description": "Service account authentication (GCP, AWS)", + "properties": { + "method": { + "type": "string", + "const": "service_account" + }, + "provider": { + "type": "string", + "enum": [ + "gcp", + "aws" + ], + "description": "Cloud provider" + }, + "credentials": { + "type": "object", + "description": "Service account credentials", + "additionalProperties": true + } + }, + "required": [ + "method", + "provider" + ] + }, + { + "type": "object", + "description": "Pre-signed URL (credentials embedded in URL)", + "properties": { + "method": { + "type": "string", + "const": "signed_url" + } + }, + "required": [ + "method" + ] + } + ] + } + } + } + ] + }, + "description": "Content that passes the standards" + }, + "fail": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "description": "URL reference - specific page to fetch and evaluate", + "properties": { + "type": { + "type": "string", + "const": "url", + "description": "Indicates this is a URL reference" + }, + "value": { + "type": "string", + "format": "uri", + "description": "Full URL to a specific page (e.g., 'https://news.example.com/controversial-article')" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for content at this URL" + } + }, + "required": [ + "type", + "value" + ] + }, + { + "title": "Artifact", + "description": "Full artifact with pre-extracted content (text, images, video, audio)", + "type": "object", + "properties": { + "property_id": { + "title": "Identifier", + "description": "Identifier for the property where this artifact appears", + "type": "object", + "properties": { + "type": { + "title": "Property Identifier Types", + "description": "Type of identifier", + "type": "string", + "enum": [ + "domain", + "subdomain", + "network_id", + "ios_bundle", + "android_package", + "apple_app_store_id", + "google_play_id", + "roku_store_id", + "fire_tv_asin", + "samsung_app_id", + "apple_tv_bundle", + "bundle_id", + "venue_id", + "screen_id", + "openooh_venue_type", + "rss_url", + "apple_podcast_id", + "spotify_show_id", + "podcast_guid" + ], + "examples": [ + "domain", + "ios_bundle", + "venue_id", + "apple_podcast_id" + ] + }, + "value": { + "type": "string", + "description": "The identifier value. For domain type: 'example.com' matches base domain plus www and m subdomains; 'edition.example.com' matches that specific subdomain; '*.example.com' matches ALL subdomains but NOT base domain" + } + }, + "required": [ + "type", + "value" + ], + "additionalProperties": false + }, + "artifact_id": { + "type": "string", + "description": "Identifier for this artifact within the property. The property owner defines the scheme (e.g., 'article_12345', 'episode_42_segment_3', 'post_abc123')." + }, + "variant_id": { + "type": "string", + "description": "Identifies a specific variant of this artifact. Use for A/B tests, translations, or temporal versions. Examples: 'en', 'es-MX', 'v2', 'headline_test_b'. The combination of artifact_id + variant_id must be unique." + }, + "format_id": { + "title": "Format ID", + "description": "Optional reference to a format definition. Uses the same format registry as creative formats.", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "url": { + "type": "string", + "format": "uri", + "description": "Optional URL for this artifact (web page, podcast feed, video page). Not all artifacts have URLs (e.g., Instagram content, podcast segments, TV scenes)." + }, + "published_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was published (ISO 8601 format)" + }, + "last_update_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was last modified (ISO 8601 format)" + }, + "assets": { + "type": "array", + "description": "Artifact assets in document flow order - text blocks, images, video, audio", + "items": { + "oneOf": [ + { + "type": "object", + "description": "Text block (paragraph, heading, etc.)", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "role": { + "type": "string", + "enum": [ + "title", + "paragraph", + "heading", + "caption", + "quote", + "list_item", + "description" + ], + "description": "Role of this text in the document. Use 'title' for the main artifact title, 'description' for summaries." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for this text (e.g., 'en', 'es-MX'). Useful when artifact contains mixed-language content." + }, + "heading_level": { + "type": "integer", + "minimum": 1, + "maximum": 6, + "description": "Heading level (1-6), only for role=heading" + } + }, + "required": [ + "type", + "content" + ] + }, + { + "type": "object", + "description": "Image asset", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Image URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "alt_text": { + "type": "string", + "description": "Alt text or image description" + }, + "caption": { + "type": "string", + "description": "Image caption" + }, + "width": { + "type": "integer", + "description": "Image width in pixels" + }, + "height": { + "type": "integer", + "description": "Image height in pixels" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Video asset", + "properties": { + "type": { + "type": "string", + "const": "video" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Video URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Video duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Video transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "subtitles", + "closed_captions", + "dub", + "generated" + ], + "description": "How the transcript was generated" + }, + "thumbnail_url": { + "type": "string", + "format": "uri", + "description": "Video thumbnail URL" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Audio asset", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Audio URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Audio duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Audio transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "closed_captions", + "generated" + ], + "description": "How the transcript was generated" + } + }, + "required": [ + "type", + "url" + ] + } + ] + } + }, + "metadata": { + "type": "object", + "description": "Rich metadata extracted from the artifact", + "properties": { + "canonical": { + "type": "string", + "format": "uri", + "description": "Canonical URL" + }, + "author": { + "type": "string", + "description": "Artifact author name" + }, + "keywords": { + "type": "string", + "description": "Artifact keywords" + }, + "open_graph": { + "type": "object", + "description": "Open Graph protocol metadata", + "additionalProperties": true + }, + "twitter_card": { + "type": "object", + "description": "Twitter Card metadata", + "additionalProperties": true + }, + "json_ld": { + "type": "array", + "description": "JSON-LD structured data (schema.org)", + "items": { + "type": "object" + } + } + }, + "additionalProperties": true + }, + "identifiers": { + "type": "object", + "description": "Platform-specific identifiers for this artifact", + "properties": { + "apple_podcast_id": { + "type": "string", + "description": "Apple Podcasts ID" + }, + "spotify_show_id": { + "type": "string", + "description": "Spotify show ID" + }, + "podcast_guid": { + "type": "string", + "description": "Podcast GUID (from RSS feed)" + }, + "youtube_video_id": { + "type": "string", + "description": "YouTube video ID" + }, + "rss_url": { + "type": "string", + "format": "uri", + "description": "RSS feed URL" + } + }, + "additionalProperties": true + } + }, + "required": [ + "property_id", + "artifact_id", + "assets" + ], + "additionalProperties": true, + "$defs": { + "asset_access": { + "type": "object", + "description": "Authentication for accessing secured asset URLs", + "oneOf": [ + { + "type": "object", + "description": "Bearer token authentication", + "properties": { + "method": { + "type": "string", + "const": "bearer_token" + }, + "token": { + "type": "string", + "description": "OAuth2 bearer token for Authorization header" + } + }, + "required": [ + "method", + "token" + ] + }, + { + "type": "object", + "description": "Service account authentication (GCP, AWS)", + "properties": { + "method": { + "type": "string", + "const": "service_account" + }, + "provider": { + "type": "string", + "enum": [ + "gcp", + "aws" + ], + "description": "Cloud provider" + }, + "credentials": { + "type": "object", + "description": "Service account credentials", + "additionalProperties": true + } + }, + "required": [ + "method", + "provider" + ] + }, + { + "type": "object", + "description": "Pre-signed URL (credentials embedded in URL)", + "properties": { + "method": { + "type": "string", + "const": "signed_url" + } + }, + "required": [ + "method" + ] + } + ] + } + } + } + ] + }, + "description": "Content that fails the standards" + } + } + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "scope", + "policy" + ], + "additionalProperties": true, + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.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/dist/schemas/3.0.0-beta.4/bundled/content-standards/create-content-standards-response.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/create-content-standards-response.json new file mode 100644 index 000000000..84f509ae0 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/create-content-standards-response.json @@ -0,0 +1,112 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/create-content-standards-response.json", + "title": "Create Content Standards Response", + "description": "Response payload for creating a content standards configuration", + "type": "object", + "oneOf": [ + { + "type": "object", + "description": "Success response - returns the created standards identifier", + "properties": { + "standards_id": { + "type": "string", + "description": "Unique identifier for the created standards configuration" + }, + "errors": { + "not": {}, + "description": "Field must not be present in success response" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "standards_id" + ] + }, + { + "type": "object", + "description": "Error response", + "properties": { + "errors": { + "type": "array", + "items": { + "title": "Error", + "description": "Standard error structure for task-specific errors and warnings", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Error code for programmatic handling" + }, + "message": { + "type": "string", + "description": "Human-readable error message" + }, + "field": { + "type": "string", + "description": "Field path associated with the error (e.g., 'packages[0].targeting')" + }, + "suggestion": { + "type": "string", + "description": "Suggested fix for the error" + }, + "retry_after": { + "type": "number", + "description": "Seconds to wait before retrying the operation", + "minimum": 0 + }, + "details": { + "type": "object", + "description": "Additional task-specific error details", + "additionalProperties": true + } + }, + "required": [ + "code", + "message" + ], + "additionalProperties": true + } + }, + "conflicting_standards_id": { + "type": "string", + "description": "If the error is a scope conflict, the ID of the existing standards that conflict" + }, + "standards_id": { + "not": {}, + "description": "Field must not be present in error response" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "errors" + ] + } + ], + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.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/dist/schemas/3.0.0-beta.4/bundled/content-standards/get-content-standards-request.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/get-content-standards-request.json new file mode 100644 index 000000000..68c4fc311 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/get-content-standards-request.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/get-content-standards-request.json", + "title": "Get Content Standards Request", + "description": "Request parameters for retrieving content safety policies", + "type": "object", + "properties": { + "standards_id": { + "type": "string", + "description": "Identifier for the standards configuration to retrieve" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "standards_id" + ], + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.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/dist/schemas/3.0.0-beta.4/bundled/content-standards/get-content-standards-response.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/get-content-standards-response.json new file mode 100644 index 000000000..bf5decb36 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/get-content-standards-response.json @@ -0,0 +1,1993 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/get-content-standards-response.json", + "title": "Get Content Standards Response", + "description": "Response payload with content safety policies", + "type": "object", + "oneOf": [ + { + "type": "object", + "description": "Success response - returns the content standards configuration", + "allOf": [ + { + "title": "Content Standards", + "description": "A content standards configuration defining brand safety and suitability policies. Standards are scoped by brand, geography, and channel. Multiple standards can be active simultaneously for different scopes.", + "type": "object", + "properties": { + "standards_id": { + "type": "string", + "description": "Unique identifier for this standards configuration" + }, + "name": { + "type": "string", + "description": "Human-readable name for this standards configuration" + }, + "countries_all": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "ISO 3166-1 alpha-2 country codes. Standards apply in ALL listed countries (AND logic)." + }, + "channels_any": { + "type": "array", + "items": { + "title": "Media Channel", + "description": "Standardized advertising media channels describing how buyers allocate budget. Channels are planning abstractions, not technical substrates. See the Media Channel Taxonomy specification for detailed definitions.", + "type": "string", + "enum": [ + "display", + "olv", + "social", + "search", + "ctv", + "linear_tv", + "radio", + "streaming_audio", + "podcast", + "dooh", + "ooh", + "print", + "cinema", + "email", + "gaming", + "retail_media", + "influencer", + "affiliate", + "product_placement" + ], + "enumDescriptions": { + "display": "Digital display advertising (banners, native, rich media) across web and app", + "olv": "Online video advertising outside CTV (pre-roll, outstream, in-app video)", + "social": "Social media platforms (Facebook, Instagram, TikTok, LinkedIn, etc.)", + "search": "Search engine advertising and search networks", + "ctv": "Connected TV and streaming on television screens", + "linear_tv": "Traditional broadcast and cable television", + "radio": "Traditional AM/FM radio broadcast", + "streaming_audio": "Digital audio streaming services (Spotify, Pandora, etc.)", + "podcast": "Podcast advertising (host-read or dynamically inserted)", + "dooh": "Digital out-of-home screens in public spaces", + "ooh": "Classic out-of-home (physical billboards, transit, etc.)", + "print": "Newspapers, magazines, and other print publications", + "cinema": "Movie theater advertising", + "email": "Email advertising and sponsored newsletter content", + "gaming": "In-game advertising across platforms", + "retail_media": "Retail media networks and commerce marketplaces (Amazon, Walmart, Instacart)", + "influencer": "Creator and influencer marketing partnerships", + "affiliate": "Affiliate networks, comparison sites, and performance-based partnerships", + "product_placement": "Product placement, branded content, and sponsorship integrations" + } + }, + "minItems": 1, + "description": "Advertising channels. Standards apply to ANY of the listed channels (OR logic)." + }, + "languages_any": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "BCP 47 language tags (e.g., 'en', 'de', 'fr'). Standards apply to content in ANY of these languages (OR logic). Content in unlisted languages is not covered by these standards." + }, + "policy": { + "type": "string", + "description": "Natural language policy describing acceptable and unacceptable content contexts. Used by LLMs and human reviewers to make judgments." + }, + "calibration_exemplars": { + "type": "object", + "description": "Training/test set to calibrate policy interpretation. Provides concrete examples of pass/fail decisions.", + "properties": { + "pass": { + "type": "array", + "items": { + "title": "Artifact", + "description": "Content artifact for safety and suitability evaluation. An artifact represents content adjacent to an ad placement - a news article, podcast segment, video chapter, or social post. Artifacts are collections of assets (text, images, video, audio) plus metadata and signals.", + "type": "object", + "properties": { + "property_id": { + "title": "Identifier", + "description": "Identifier for the property where this artifact appears", + "type": "object", + "properties": { + "type": { + "title": "Property Identifier Types", + "description": "Type of identifier", + "type": "string", + "enum": [ + "domain", + "subdomain", + "network_id", + "ios_bundle", + "android_package", + "apple_app_store_id", + "google_play_id", + "roku_store_id", + "fire_tv_asin", + "samsung_app_id", + "apple_tv_bundle", + "bundle_id", + "venue_id", + "screen_id", + "openooh_venue_type", + "rss_url", + "apple_podcast_id", + "spotify_show_id", + "podcast_guid" + ], + "examples": [ + "domain", + "ios_bundle", + "venue_id", + "apple_podcast_id" + ] + }, + "value": { + "type": "string", + "description": "The identifier value. For domain type: 'example.com' matches base domain plus www and m subdomains; 'edition.example.com' matches that specific subdomain; '*.example.com' matches ALL subdomains but NOT base domain" + } + }, + "required": [ + "type", + "value" + ], + "additionalProperties": false + }, + "artifact_id": { + "type": "string", + "description": "Identifier for this artifact within the property. The property owner defines the scheme (e.g., 'article_12345', 'episode_42_segment_3', 'post_abc123')." + }, + "variant_id": { + "type": "string", + "description": "Identifies a specific variant of this artifact. Use for A/B tests, translations, or temporal versions. Examples: 'en', 'es-MX', 'v2', 'headline_test_b'. The combination of artifact_id + variant_id must be unique." + }, + "format_id": { + "title": "Format ID", + "description": "Optional reference to a format definition. Uses the same format registry as creative formats.", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "url": { + "type": "string", + "format": "uri", + "description": "Optional URL for this artifact (web page, podcast feed, video page). Not all artifacts have URLs (e.g., Instagram content, podcast segments, TV scenes)." + }, + "published_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was published (ISO 8601 format)" + }, + "last_update_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was last modified (ISO 8601 format)" + }, + "assets": { + "type": "array", + "description": "Artifact assets in document flow order - text blocks, images, video, audio", + "items": { + "oneOf": [ + { + "type": "object", + "description": "Text block (paragraph, heading, etc.)", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "role": { + "type": "string", + "enum": [ + "title", + "paragraph", + "heading", + "caption", + "quote", + "list_item", + "description" + ], + "description": "Role of this text in the document. Use 'title' for the main artifact title, 'description' for summaries." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for this text (e.g., 'en', 'es-MX'). Useful when artifact contains mixed-language content." + }, + "heading_level": { + "type": "integer", + "minimum": 1, + "maximum": 6, + "description": "Heading level (1-6), only for role=heading" + } + }, + "required": [ + "type", + "content" + ] + }, + { + "type": "object", + "description": "Image asset", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Image URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "alt_text": { + "type": "string", + "description": "Alt text or image description" + }, + "caption": { + "type": "string", + "description": "Image caption" + }, + "width": { + "type": "integer", + "description": "Image width in pixels" + }, + "height": { + "type": "integer", + "description": "Image height in pixels" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Video asset", + "properties": { + "type": { + "type": "string", + "const": "video" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Video URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Video duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Video transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "subtitles", + "closed_captions", + "dub", + "generated" + ], + "description": "How the transcript was generated" + }, + "thumbnail_url": { + "type": "string", + "format": "uri", + "description": "Video thumbnail URL" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Audio asset", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Audio URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Audio duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Audio transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "closed_captions", + "generated" + ], + "description": "How the transcript was generated" + } + }, + "required": [ + "type", + "url" + ] + } + ] + } + }, + "metadata": { + "type": "object", + "description": "Rich metadata extracted from the artifact", + "properties": { + "canonical": { + "type": "string", + "format": "uri", + "description": "Canonical URL" + }, + "author": { + "type": "string", + "description": "Artifact author name" + }, + "keywords": { + "type": "string", + "description": "Artifact keywords" + }, + "open_graph": { + "type": "object", + "description": "Open Graph protocol metadata", + "additionalProperties": true + }, + "twitter_card": { + "type": "object", + "description": "Twitter Card metadata", + "additionalProperties": true + }, + "json_ld": { + "type": "array", + "description": "JSON-LD structured data (schema.org)", + "items": { + "type": "object" + } + } + }, + "additionalProperties": true + }, + "identifiers": { + "type": "object", + "description": "Platform-specific identifiers for this artifact", + "properties": { + "apple_podcast_id": { + "type": "string", + "description": "Apple Podcasts ID" + }, + "spotify_show_id": { + "type": "string", + "description": "Spotify show ID" + }, + "podcast_guid": { + "type": "string", + "description": "Podcast GUID (from RSS feed)" + }, + "youtube_video_id": { + "type": "string", + "description": "YouTube video ID" + }, + "rss_url": { + "type": "string", + "format": "uri", + "description": "RSS feed URL" + } + }, + "additionalProperties": true + } + }, + "required": [ + "property_id", + "artifact_id", + "assets" + ], + "additionalProperties": true, + "$defs": { + "asset_access": { + "type": "object", + "description": "Authentication for accessing secured asset URLs", + "oneOf": [ + { + "type": "object", + "description": "Bearer token authentication", + "properties": { + "method": { + "type": "string", + "const": "bearer_token" + }, + "token": { + "type": "string", + "description": "OAuth2 bearer token for Authorization header" + } + }, + "required": [ + "method", + "token" + ] + }, + { + "type": "object", + "description": "Service account authentication (GCP, AWS)", + "properties": { + "method": { + "type": "string", + "const": "service_account" + }, + "provider": { + "type": "string", + "enum": [ + "gcp", + "aws" + ], + "description": "Cloud provider" + }, + "credentials": { + "type": "object", + "description": "Service account credentials", + "additionalProperties": true + } + }, + "required": [ + "method", + "provider" + ] + }, + { + "type": "object", + "description": "Pre-signed URL (credentials embedded in URL)", + "properties": { + "method": { + "type": "string", + "const": "signed_url" + } + }, + "required": [ + "method" + ] + } + ] + } + } + }, + "description": "Artifacts that pass the content standards" + }, + "fail": { + "type": "array", + "items": { + "title": "Artifact", + "description": "Content artifact for safety and suitability evaluation. An artifact represents content adjacent to an ad placement - a news article, podcast segment, video chapter, or social post. Artifacts are collections of assets (text, images, video, audio) plus metadata and signals.", + "type": "object", + "properties": { + "property_id": { + "title": "Identifier", + "description": "Identifier for the property where this artifact appears", + "type": "object", + "properties": { + "type": { + "title": "Property Identifier Types", + "description": "Type of identifier", + "type": "string", + "enum": [ + "domain", + "subdomain", + "network_id", + "ios_bundle", + "android_package", + "apple_app_store_id", + "google_play_id", + "roku_store_id", + "fire_tv_asin", + "samsung_app_id", + "apple_tv_bundle", + "bundle_id", + "venue_id", + "screen_id", + "openooh_venue_type", + "rss_url", + "apple_podcast_id", + "spotify_show_id", + "podcast_guid" + ], + "examples": [ + "domain", + "ios_bundle", + "venue_id", + "apple_podcast_id" + ] + }, + "value": { + "type": "string", + "description": "The identifier value. For domain type: 'example.com' matches base domain plus www and m subdomains; 'edition.example.com' matches that specific subdomain; '*.example.com' matches ALL subdomains but NOT base domain" + } + }, + "required": [ + "type", + "value" + ], + "additionalProperties": false + }, + "artifact_id": { + "type": "string", + "description": "Identifier for this artifact within the property. The property owner defines the scheme (e.g., 'article_12345', 'episode_42_segment_3', 'post_abc123')." + }, + "variant_id": { + "type": "string", + "description": "Identifies a specific variant of this artifact. Use for A/B tests, translations, or temporal versions. Examples: 'en', 'es-MX', 'v2', 'headline_test_b'. The combination of artifact_id + variant_id must be unique." + }, + "format_id": { + "title": "Format ID", + "description": "Optional reference to a format definition. Uses the same format registry as creative formats.", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "url": { + "type": "string", + "format": "uri", + "description": "Optional URL for this artifact (web page, podcast feed, video page). Not all artifacts have URLs (e.g., Instagram content, podcast segments, TV scenes)." + }, + "published_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was published (ISO 8601 format)" + }, + "last_update_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was last modified (ISO 8601 format)" + }, + "assets": { + "type": "array", + "description": "Artifact assets in document flow order - text blocks, images, video, audio", + "items": { + "oneOf": [ + { + "type": "object", + "description": "Text block (paragraph, heading, etc.)", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "role": { + "type": "string", + "enum": [ + "title", + "paragraph", + "heading", + "caption", + "quote", + "list_item", + "description" + ], + "description": "Role of this text in the document. Use 'title' for the main artifact title, 'description' for summaries." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for this text (e.g., 'en', 'es-MX'). Useful when artifact contains mixed-language content." + }, + "heading_level": { + "type": "integer", + "minimum": 1, + "maximum": 6, + "description": "Heading level (1-6), only for role=heading" + } + }, + "required": [ + "type", + "content" + ] + }, + { + "type": "object", + "description": "Image asset", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Image URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "alt_text": { + "type": "string", + "description": "Alt text or image description" + }, + "caption": { + "type": "string", + "description": "Image caption" + }, + "width": { + "type": "integer", + "description": "Image width in pixels" + }, + "height": { + "type": "integer", + "description": "Image height in pixels" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Video asset", + "properties": { + "type": { + "type": "string", + "const": "video" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Video URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Video duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Video transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "subtitles", + "closed_captions", + "dub", + "generated" + ], + "description": "How the transcript was generated" + }, + "thumbnail_url": { + "type": "string", + "format": "uri", + "description": "Video thumbnail URL" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Audio asset", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Audio URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Audio duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Audio transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "closed_captions", + "generated" + ], + "description": "How the transcript was generated" + } + }, + "required": [ + "type", + "url" + ] + } + ] + } + }, + "metadata": { + "type": "object", + "description": "Rich metadata extracted from the artifact", + "properties": { + "canonical": { + "type": "string", + "format": "uri", + "description": "Canonical URL" + }, + "author": { + "type": "string", + "description": "Artifact author name" + }, + "keywords": { + "type": "string", + "description": "Artifact keywords" + }, + "open_graph": { + "type": "object", + "description": "Open Graph protocol metadata", + "additionalProperties": true + }, + "twitter_card": { + "type": "object", + "description": "Twitter Card metadata", + "additionalProperties": true + }, + "json_ld": { + "type": "array", + "description": "JSON-LD structured data (schema.org)", + "items": { + "type": "object" + } + } + }, + "additionalProperties": true + }, + "identifiers": { + "type": "object", + "description": "Platform-specific identifiers for this artifact", + "properties": { + "apple_podcast_id": { + "type": "string", + "description": "Apple Podcasts ID" + }, + "spotify_show_id": { + "type": "string", + "description": "Spotify show ID" + }, + "podcast_guid": { + "type": "string", + "description": "Podcast GUID (from RSS feed)" + }, + "youtube_video_id": { + "type": "string", + "description": "YouTube video ID" + }, + "rss_url": { + "type": "string", + "format": "uri", + "description": "RSS feed URL" + } + }, + "additionalProperties": true + } + }, + "required": [ + "property_id", + "artifact_id", + "assets" + ], + "additionalProperties": true, + "$defs": { + "asset_access": { + "type": "object", + "description": "Authentication for accessing secured asset URLs", + "oneOf": [ + { + "type": "object", + "description": "Bearer token authentication", + "properties": { + "method": { + "type": "string", + "const": "bearer_token" + }, + "token": { + "type": "string", + "description": "OAuth2 bearer token for Authorization header" + } + }, + "required": [ + "method", + "token" + ] + }, + { + "type": "object", + "description": "Service account authentication (GCP, AWS)", + "properties": { + "method": { + "type": "string", + "const": "service_account" + }, + "provider": { + "type": "string", + "enum": [ + "gcp", + "aws" + ], + "description": "Cloud provider" + }, + "credentials": { + "type": "object", + "description": "Service account credentials", + "additionalProperties": true + } + }, + "required": [ + "method", + "provider" + ] + }, + { + "type": "object", + "description": "Pre-signed URL (credentials embedded in URL)", + "properties": { + "method": { + "type": "string", + "const": "signed_url" + } + }, + "required": [ + "method" + ] + } + ] + } + } + }, + "description": "Artifacts that fail the content standards" + } + } + }, + "pricing_options": { + "type": "array", + "description": "Pricing options for this content standards service. The buyer passes the selected pricing_option_id in report_usage for billing verification.", + "items": { + "title": "Pricing Option", + "description": "A pricing model option offered by a publisher for a product. Discriminated by pricing_model field. If fixed_price is present, it's fixed pricing. If absent, it's auction-based (floor_price and price_guidance optional). Bid-based auction models may also include max_bid as a boolean signal to interpret bid_price as a buyer ceiling instead of an exact honored price.", + "oneOf": [ + { + "title": "CPM Pricing Option", + "description": "Cost Per Mille (cost per 1,000 impressions) pricing. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "cpm", + "description": "Cost per 1,000 impressions" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per unit. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "max_bid": { + "type": "boolean", + "description": "When true, bid_price is interpreted as the buyer's maximum willingness to pay (ceiling) rather than an exact price. Sellers may optimize actual clearing prices between floor_price and bid_price based on delivery pacing. When false or absent, bid_price (if provided) is the exact bid/price to honor.", + "default": false + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency" + ], + "additionalProperties": true + }, + { + "title": "vCPM Pricing Option", + "description": "Viewable Cost Per Mille (cost per 1,000 viewable impressions) pricing - MRC viewability standard. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "vcpm", + "description": "Cost per 1,000 viewable impressions (MRC standard)" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per unit. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "max_bid": { + "type": "boolean", + "description": "When true, bid_price is interpreted as the buyer's maximum willingness to pay (ceiling) rather than an exact price. Sellers may optimize actual clearing prices between floor_price and bid_price based on delivery pacing. When false or absent, bid_price (if provided) is the exact bid/price to honor.", + "default": false + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency" + ], + "additionalProperties": true + }, + { + "title": "CPC Pricing Option", + "description": "Cost Per Click pricing. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "cpc", + "description": "Cost per click" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per click. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "max_bid": { + "type": "boolean", + "description": "When true, bid_price is interpreted as the buyer's maximum willingness to pay (ceiling) rather than an exact price. Sellers may optimize actual clearing prices between floor_price and bid_price based on delivery pacing. When false or absent, bid_price (if provided) is the exact bid/price to honor.", + "default": false + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency" + ], + "additionalProperties": true + }, + { + "title": "CPCV Pricing Option", + "description": "Cost Per Completed View (100% video/audio completion) pricing. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "cpcv", + "description": "Cost per completed view (100% completion)" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per completed view. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "max_bid": { + "type": "boolean", + "description": "When true, bid_price is interpreted as the buyer's maximum willingness to pay (ceiling) rather than an exact price. Sellers may optimize actual clearing prices between floor_price and bid_price based on delivery pacing. When false or absent, bid_price (if provided) is the exact bid/price to honor.", + "default": false + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency" + ], + "additionalProperties": true + }, + { + "title": "CPV Pricing Option", + "description": "Cost Per View (at publisher-defined threshold) pricing for video/audio. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "cpv", + "description": "Cost per view at threshold" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per view. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "max_bid": { + "type": "boolean", + "description": "When true, bid_price is interpreted as the buyer's maximum willingness to pay (ceiling) rather than an exact price. Sellers may optimize actual clearing prices between floor_price and bid_price based on delivery pacing. When false or absent, bid_price (if provided) is the exact bid/price to honor.", + "default": false + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "parameters": { + "type": "object", + "description": "CPV-specific parameters defining the view threshold", + "properties": { + "view_threshold": { + "oneOf": [ + { + "type": "number", + "description": "Percentage completion threshold (0.0 to 1.0, e.g., 0.5 = 50%)", + "minimum": 0, + "maximum": 1 + }, + { + "type": "object", + "description": "Time-based view threshold", + "properties": { + "duration_seconds": { + "type": "integer", + "description": "Seconds of viewing required", + "minimum": 1 + } + }, + "required": [ + "duration_seconds" + ], + "additionalProperties": true + } + ] + } + }, + "required": [ + "view_threshold" + ], + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency", + "parameters" + ], + "additionalProperties": true + }, + { + "title": "CPP Pricing Option", + "description": "Cost Per Point (Gross Rating Point) pricing for TV and audio campaigns. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "cpp", + "description": "Cost per Gross Rating Point" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per rating point. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "parameters": { + "type": "object", + "description": "CPP-specific parameters for demographic targeting", + "properties": { + "demographic_system": { + "title": "Demographic System", + "description": "Measurement system for the demographic field. Defaults to nielsen when omitted.", + "type": "string", + "enum": [ + "nielsen", + "barb", + "agf", + "oztam", + "mediametrie", + "custom" + ], + "enumDescriptions": { + "nielsen": "Nielsen notation. Prefix: P(ersons), M(en), W(omen), A(dults), C(hildren), T(eens) + age range. Examples: P18-49, M25-54, W35+", + "barb": "BARB (UK). NRS social grade + age bands. Examples: ABC1 Adults, 16-34, Adults", + "agf": "AGF Videoforschung (Germany). Erwachsene notation + age bands. Examples: E 14-49, E 14+", + "oztam": "OzTAM (Australia). Age/gender bands, 4+ measurement universe", + "mediametrie": "Mediametrie (France). Named segments + age bands", + "custom": "Publisher-defined demographic notation" + } + }, + "demographic": { + "type": "string", + "description": "Target demographic code within the specified demographic_system (e.g., P18-49 for Nielsen, ABC1 Adults for BARB)" + }, + "min_points": { + "type": "number", + "description": "Minimum GRPs/TRPs required", + "minimum": 0 + } + }, + "required": [ + "demographic" + ], + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency", + "parameters" + ], + "additionalProperties": true + }, + { + "title": "CPA Pricing Option", + "description": "Cost Per Acquisition pricing. Advertiser pays a fixed price when a specified conversion event occurs. The event_type field declares which event triggers billing (e.g., purchase, lead, app_install).", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "cpa", + "description": "Cost per acquisition (conversion event)" + }, + "event_type": { + "allOf": [ + { + "title": "Event Type", + "description": "Standard marketing event types for event logging, aligned with IAB ECAPI", + "type": "string", + "enum": [ + "page_view", + "view_content", + "select_content", + "select_item", + "search", + "share", + "add_to_cart", + "remove_from_cart", + "viewed_cart", + "add_to_wishlist", + "initiate_checkout", + "add_payment_info", + "purchase", + "refund", + "lead", + "qualify_lead", + "close_convert_lead", + "disqualify_lead", + "complete_registration", + "subscribe", + "start_trial", + "app_install", + "app_launch", + "contact", + "schedule", + "donate", + "submit_application", + "custom" + ], + "enumDescriptions": { + "page_view": "User viewed a page", + "view_content": "User viewed specific content (product, article, etc.)", + "select_content": "User selected or clicked on content (article, video, etc.)", + "select_item": "User selected a specific product or item from a list", + "search": "User performed a search", + "share": "User shared content via social or messaging", + "add_to_cart": "User added an item to cart", + "remove_from_cart": "User removed an item from cart", + "viewed_cart": "User viewed their shopping cart", + "add_to_wishlist": "User added an item to a wishlist", + "initiate_checkout": "User started checkout process", + "add_payment_info": "User added payment information", + "purchase": "User completed a purchase", + "refund": "A purchase was fully or partially refunded (adjusts ROAS)", + "lead": "User expressed interest (form submission, signup, etc.)", + "qualify_lead": "Lead qualified by sales or scoring criteria", + "close_convert_lead": "Lead converted to a customer or closed deal", + "disqualify_lead": "Lead disqualified or marked as not viable", + "complete_registration": "User completed account registration", + "subscribe": "User subscribed to a service or newsletter", + "start_trial": "User started a free trial", + "app_install": "User installed an application", + "app_launch": "User launched an application", + "contact": "User initiated contact (call, message, etc.)", + "schedule": "User scheduled an appointment or event", + "donate": "User made a donation", + "submit_application": "User submitted an application (loan, job, etc.)", + "custom": "Custom event type (specify in custom_event_name)" + } + } + ], + "description": "The conversion event type that triggers billing (e.g., purchase, lead, app_install)" + }, + "custom_event_name": { + "type": "string", + "description": "Name of the custom event when event_type is 'custom'. Required when event_type is 'custom', ignored otherwise." + }, + "event_source_id": { + "type": "string", + "description": "When present, only events from this specific event source count toward billing. Allows different CPA rates for different sources (e.g., online vs in-store purchases). Must match an event source configured via sync_event_sources." + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per acquisition in the specified currency", + "exclusiveMinimum": 0 + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "event_type", + "currency", + "fixed_price" + ], + "additionalProperties": true + }, + { + "title": "Flat Rate Pricing Option", + "description": "Flat rate pricing for DOOH, sponsorships, and time-based campaigns. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "flat_rate", + "description": "Fixed cost regardless of delivery volume" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Flat rate cost. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "parameters": { + "type": "object", + "description": "Flat rate parameters for DOOH and time-based campaigns", + "properties": { + "duration_hours": { + "type": "number", + "description": "Duration in hours for time-based pricing", + "minimum": 0 + }, + "sov_percentage": { + "type": "number", + "description": "Guaranteed share of voice (0-100)", + "minimum": 0, + "maximum": 100 + }, + "loop_duration_seconds": { + "type": "integer", + "description": "Duration of ad loop rotation in seconds", + "minimum": 1 + }, + "min_plays_per_hour": { + "type": "integer", + "description": "Minimum plays per hour", + "minimum": 0 + }, + "venue_package": { + "type": "string", + "description": "Named venue package identifier" + }, + "estimated_impressions": { + "type": "integer", + "description": "Estimated impressions (informational)", + "minimum": 0 + }, + "daypart": { + "type": "string", + "description": "Specific daypart for time-based pricing" + } + }, + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency" + ], + "additionalProperties": true + }, + { + "title": "Time-Based Pricing Option", + "description": "Cost per time unit (hour, day, week, or month) - rate scales with campaign duration. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "time", + "description": "Cost per time unit - rate scales with campaign duration" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Cost per time unit. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid per time unit for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "parameters": { + "type": "object", + "description": "Time-based pricing parameters", + "required": [ + "time_unit" + ], + "properties": { + "time_unit": { + "type": "string", + "enum": [ + "hour", + "day", + "week", + "month" + ], + "description": "The time unit for pricing. Total cost = fixed_price × number of time_units in the campaign flight." + }, + "min_duration": { + "type": "integer", + "minimum": 1, + "description": "Minimum booking duration in time_units" + }, + "max_duration": { + "type": "integer", + "minimum": 1, + "description": "Maximum booking duration in time_units. Must be >= min_duration when both are present." + } + }, + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency", + "parameters" + ], + "additionalProperties": true + } + ] + }, + "minItems": 1 + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "standards_id" + ] + } + ], + "properties": { + "errors": { + "not": {}, + "description": "Field must not be present in success response" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + } + } + }, + { + "type": "object", + "description": "Error response", + "properties": { + "errors": { + "type": "array", + "items": { + "title": "Error", + "description": "Standard error structure for task-specific errors and warnings", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Error code for programmatic handling" + }, + "message": { + "type": "string", + "description": "Human-readable error message" + }, + "field": { + "type": "string", + "description": "Field path associated with the error (e.g., 'packages[0].targeting')" + }, + "suggestion": { + "type": "string", + "description": "Suggested fix for the error" + }, + "retry_after": { + "type": "number", + "description": "Seconds to wait before retrying the operation", + "minimum": 0 + }, + "details": { + "type": "object", + "description": "Additional task-specific error details", + "additionalProperties": true + } + }, + "required": [ + "code", + "message" + ], + "additionalProperties": true + } + }, + "standards_id": { + "not": {}, + "description": "Field must not be present in error response" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "errors" + ] + } + ], + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.777Z", + "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/dist/schemas/3.0.0-beta.4/bundled/content-standards/get-media-buy-artifacts-request.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/get-media-buy-artifacts-request.json new file mode 100644 index 000000000..ab1c0038a --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/get-media-buy-artifacts-request.json @@ -0,0 +1,189 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/get-media-buy-artifacts-request.json", + "title": "Get Media Buy Artifacts Request", + "description": "Request parameters for retrieving content artifacts from a media buy for validation", + "type": "object", + "properties": { + "account": { + "title": "Account Reference", + "description": "Filter artifacts to a specific account. When omitted, returns artifacts across all accessible accounts.", + "type": "object", + "oneOf": [ + { + "properties": { + "account_id": { + "type": "string", + "description": "Seller-assigned account identifier (from sync_accounts or list_accounts)" + } + }, + "required": [ + "account_id" + ], + "additionalProperties": false + }, + { + "properties": { + "brand": { + "title": "Brand Reference", + "description": "Brand reference identifying the advertiser", + "type": "object", + "properties": { + "domain": { + "type": "string", + "description": "Domain where /.well-known/brand.json is hosted, or the brand's operating domain", + "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$" + }, + "brand_id": { + "title": "Brand ID", + "description": "Brand identifier within the house portfolio. Optional for single-brand domains.", + "type": "string", + "pattern": "^[a-z0-9_]+$", + "examples": [ + "tide", + "cheerios", + "air_jordan", + "nike", + "pampers" + ] + } + }, + "required": [ + "domain" + ], + "additionalProperties": false, + "examples": [ + { + "domain": "nova-brands.com", + "brand_id": "spark" + }, + { + "domain": "nova-brands.com", + "brand_id": "glow" + }, + { + "domain": "acme-corp.com" + } + ] + }, + "operator": { + "type": "string", + "description": "Domain of the entity operating on the brand's behalf. When the brand operates directly, this is the brand's domain.", + "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$" + } + }, + "required": [ + "brand", + "operator" + ], + "additionalProperties": false + } + ], + "examples": [ + { + "account_id": "acc_acme_001" + }, + { + "brand": { + "domain": "acme-corp.com" + }, + "operator": "acme-corp.com" + }, + { + "brand": { + "domain": "nova-brands.com", + "brand_id": "spark" + }, + "operator": "pinnacle-media.com" + } + ] + }, + "media_buy_id": { + "type": "string", + "description": "Media buy to get artifacts from" + }, + "package_ids": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "Filter to specific packages within the media buy" + }, + "sampling": { + "type": "object", + "description": "Sampling parameters. Defaults to the sampling rate agreed in the media buy.", + "properties": { + "rate": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Sampling rate (0-1). 1.0 = all deliveries, 0.25 = 25% sample." + }, + "method": { + "type": "string", + "enum": [ + "random", + "stratified", + "recent", + "failures_only" + ], + "description": "How to select the sample" + } + } + }, + "time_range": { + "type": "object", + "description": "Filter to specific time period", + "properties": { + "start": { + "type": "string", + "format": "date-time", + "description": "Start of time range (inclusive)" + }, + "end": { + "type": "string", + "format": "date-time", + "description": "End of time range (exclusive)" + } + } + }, + "pagination": { + "type": "object", + "description": "Pagination parameters. Uses higher limits than standard pagination because artifact result sets can be very large.", + "properties": { + "max_results": { + "type": "integer", + "minimum": 1, + "maximum": 10000, + "default": 1000, + "description": "Maximum number of artifacts to return per page" + }, + "cursor": { + "type": "string", + "description": "Opaque cursor from a previous response to fetch the next page" + } + }, + "additionalProperties": false + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "media_buy_id" + ], + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.778Z", + "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/dist/schemas/3.0.0-beta.4/bundled/content-standards/get-media-buy-artifacts-response.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/get-media-buy-artifacts-response.json new file mode 100644 index 000000000..2675b17d0 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/get-media-buy-artifacts-response.json @@ -0,0 +1,653 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/get-media-buy-artifacts-response.json", + "title": "Get Media Buy Artifacts Response", + "description": "Response containing content artifacts from a media buy for validation", + "type": "object", + "oneOf": [ + { + "type": "object", + "description": "Success response with artifacts", + "properties": { + "media_buy_id": { + "type": "string", + "description": "Media buy these artifacts belong to" + }, + "artifacts": { + "type": "array", + "description": "Delivery records with full artifact content", + "items": { + "type": "object", + "properties": { + "record_id": { + "type": "string", + "description": "Unique identifier for this delivery record" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "When the delivery occurred" + }, + "package_id": { + "type": "string", + "description": "Which package this delivery belongs to" + }, + "artifact": { + "title": "Artifact", + "description": "Full artifact with content assets", + "type": "object", + "properties": { + "property_id": { + "title": "Identifier", + "description": "Identifier for the property where this artifact appears", + "type": "object", + "properties": { + "type": { + "title": "Property Identifier Types", + "description": "Type of identifier", + "type": "string", + "enum": [ + "domain", + "subdomain", + "network_id", + "ios_bundle", + "android_package", + "apple_app_store_id", + "google_play_id", + "roku_store_id", + "fire_tv_asin", + "samsung_app_id", + "apple_tv_bundle", + "bundle_id", + "venue_id", + "screen_id", + "openooh_venue_type", + "rss_url", + "apple_podcast_id", + "spotify_show_id", + "podcast_guid" + ], + "examples": [ + "domain", + "ios_bundle", + "venue_id", + "apple_podcast_id" + ] + }, + "value": { + "type": "string", + "description": "The identifier value. For domain type: 'example.com' matches base domain plus www and m subdomains; 'edition.example.com' matches that specific subdomain; '*.example.com' matches ALL subdomains but NOT base domain" + } + }, + "required": [ + "type", + "value" + ], + "additionalProperties": false + }, + "artifact_id": { + "type": "string", + "description": "Identifier for this artifact within the property. The property owner defines the scheme (e.g., 'article_12345', 'episode_42_segment_3', 'post_abc123')." + }, + "variant_id": { + "type": "string", + "description": "Identifies a specific variant of this artifact. Use for A/B tests, translations, or temporal versions. Examples: 'en', 'es-MX', 'v2', 'headline_test_b'. The combination of artifact_id + variant_id must be unique." + }, + "format_id": { + "title": "Format ID", + "description": "Optional reference to a format definition. Uses the same format registry as creative formats.", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "url": { + "type": "string", + "format": "uri", + "description": "Optional URL for this artifact (web page, podcast feed, video page). Not all artifacts have URLs (e.g., Instagram content, podcast segments, TV scenes)." + }, + "published_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was published (ISO 8601 format)" + }, + "last_update_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was last modified (ISO 8601 format)" + }, + "assets": { + "type": "array", + "description": "Artifact assets in document flow order - text blocks, images, video, audio", + "items": { + "oneOf": [ + { + "type": "object", + "description": "Text block (paragraph, heading, etc.)", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "role": { + "type": "string", + "enum": [ + "title", + "paragraph", + "heading", + "caption", + "quote", + "list_item", + "description" + ], + "description": "Role of this text in the document. Use 'title' for the main artifact title, 'description' for summaries." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for this text (e.g., 'en', 'es-MX'). Useful when artifact contains mixed-language content." + }, + "heading_level": { + "type": "integer", + "minimum": 1, + "maximum": 6, + "description": "Heading level (1-6), only for role=heading" + } + }, + "required": [ + "type", + "content" + ] + }, + { + "type": "object", + "description": "Image asset", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Image URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "alt_text": { + "type": "string", + "description": "Alt text or image description" + }, + "caption": { + "type": "string", + "description": "Image caption" + }, + "width": { + "type": "integer", + "description": "Image width in pixels" + }, + "height": { + "type": "integer", + "description": "Image height in pixels" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Video asset", + "properties": { + "type": { + "type": "string", + "const": "video" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Video URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Video duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Video transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "subtitles", + "closed_captions", + "dub", + "generated" + ], + "description": "How the transcript was generated" + }, + "thumbnail_url": { + "type": "string", + "format": "uri", + "description": "Video thumbnail URL" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Audio asset", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Audio URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Audio duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Audio transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "closed_captions", + "generated" + ], + "description": "How the transcript was generated" + } + }, + "required": [ + "type", + "url" + ] + } + ] + } + }, + "metadata": { + "type": "object", + "description": "Rich metadata extracted from the artifact", + "properties": { + "canonical": { + "type": "string", + "format": "uri", + "description": "Canonical URL" + }, + "author": { + "type": "string", + "description": "Artifact author name" + }, + "keywords": { + "type": "string", + "description": "Artifact keywords" + }, + "open_graph": { + "type": "object", + "description": "Open Graph protocol metadata", + "additionalProperties": true + }, + "twitter_card": { + "type": "object", + "description": "Twitter Card metadata", + "additionalProperties": true + }, + "json_ld": { + "type": "array", + "description": "JSON-LD structured data (schema.org)", + "items": { + "type": "object" + } + } + }, + "additionalProperties": true + }, + "identifiers": { + "type": "object", + "description": "Platform-specific identifiers for this artifact", + "properties": { + "apple_podcast_id": { + "type": "string", + "description": "Apple Podcasts ID" + }, + "spotify_show_id": { + "type": "string", + "description": "Spotify show ID" + }, + "podcast_guid": { + "type": "string", + "description": "Podcast GUID (from RSS feed)" + }, + "youtube_video_id": { + "type": "string", + "description": "YouTube video ID" + }, + "rss_url": { + "type": "string", + "format": "uri", + "description": "RSS feed URL" + } + }, + "additionalProperties": true + } + }, + "required": [ + "property_id", + "artifact_id", + "assets" + ], + "additionalProperties": true, + "$defs": { + "asset_access": { + "type": "object", + "description": "Authentication for accessing secured asset URLs", + "oneOf": [ + { + "type": "object", + "description": "Bearer token authentication", + "properties": { + "method": { + "type": "string", + "const": "bearer_token" + }, + "token": { + "type": "string", + "description": "OAuth2 bearer token for Authorization header" + } + }, + "required": [ + "method", + "token" + ] + }, + { + "type": "object", + "description": "Service account authentication (GCP, AWS)", + "properties": { + "method": { + "type": "string", + "const": "service_account" + }, + "provider": { + "type": "string", + "enum": [ + "gcp", + "aws" + ], + "description": "Cloud provider" + }, + "credentials": { + "type": "object", + "description": "Service account credentials", + "additionalProperties": true + } + }, + "required": [ + "method", + "provider" + ] + }, + { + "type": "object", + "description": "Pre-signed URL (credentials embedded in URL)", + "properties": { + "method": { + "type": "string", + "const": "signed_url" + } + }, + "required": [ + "method" + ] + } + ] + } + } + }, + "country": { + "type": "string", + "description": "ISO 3166-1 alpha-2 country code where delivery occurred" + }, + "channel": { + "type": "string", + "description": "Channel type (e.g., display, video, audio, social)" + }, + "brand_context": { + "type": "object", + "description": "Brand information for policy evaluation. Schema TBD - placeholder for brand identifiers.", + "properties": { + "brand_id": { + "type": "string", + "description": "Brand identifier" + }, + "sku_id": { + "type": "string", + "description": "Product/SKU identifier if applicable" + } + } + }, + "local_verdict": { + "type": "string", + "enum": [ + "pass", + "fail", + "unevaluated" + ], + "description": "Seller's local model verdict for this artifact" + } + }, + "required": [ + "record_id", + "artifact" + ] + } + }, + "sampling_info": { + "type": "object", + "description": "Information about how the sample was generated", + "properties": { + "total_deliveries": { + "type": "integer", + "description": "Total deliveries in the time range" + }, + "sampled_count": { + "type": "integer", + "description": "Number of artifacts in this response" + }, + "effective_rate": { + "type": "number", + "description": "Actual sampling rate achieved" + }, + "method": { + "type": "string", + "enum": [ + "random", + "stratified", + "recent", + "failures_only" + ], + "description": "Sampling method used" + } + } + }, + "pagination": { + "title": "Pagination Response", + "description": "Standard cursor-based pagination metadata for list responses", + "type": "object", + "properties": { + "has_more": { + "type": "boolean", + "description": "Whether more results are available beyond this page" + }, + "cursor": { + "type": "string", + "description": "Opaque cursor to pass in the next request to fetch the next page. Only present when has_more is true." + }, + "total_count": { + "type": "integer", + "minimum": 0, + "description": "Total number of items matching the query across all pages. Optional because not all backends can efficiently compute this." + } + }, + "required": [ + "has_more" + ], + "additionalProperties": false + }, + "errors": { + "not": {}, + "description": "Field must not be present in success response" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "media_buy_id", + "artifacts" + ] + }, + { + "type": "object", + "description": "Error response", + "properties": { + "errors": { + "type": "array", + "items": { + "title": "Error", + "description": "Standard error structure for task-specific errors and warnings", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Error code for programmatic handling" + }, + "message": { + "type": "string", + "description": "Human-readable error message" + }, + "field": { + "type": "string", + "description": "Field path associated with the error (e.g., 'packages[0].targeting')" + }, + "suggestion": { + "type": "string", + "description": "Suggested fix for the error" + }, + "retry_after": { + "type": "number", + "description": "Seconds to wait before retrying the operation", + "minimum": 0 + }, + "details": { + "type": "object", + "description": "Additional task-specific error details", + "additionalProperties": true + } + }, + "required": [ + "code", + "message" + ], + "additionalProperties": true + } + }, + "media_buy_id": { + "not": {}, + "description": "Field must not be present in error response" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "errors" + ] + } + ], + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.779Z", + "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/dist/schemas/3.0.0-beta.4/bundled/content-standards/list-content-standards-request.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/list-content-standards-request.json new file mode 100644 index 000000000..6947ab2a5 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/list-content-standards-request.json @@ -0,0 +1,113 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/list-content-standards-request.json", + "title": "List Content Standards Request", + "description": "Request parameters for listing content standards configurations", + "type": "object", + "properties": { + "channels": { + "type": "array", + "items": { + "title": "Media Channel", + "description": "Standardized advertising media channels describing how buyers allocate budget. Channels are planning abstractions, not technical substrates. See the Media Channel Taxonomy specification for detailed definitions.", + "type": "string", + "enum": [ + "display", + "olv", + "social", + "search", + "ctv", + "linear_tv", + "radio", + "streaming_audio", + "podcast", + "dooh", + "ooh", + "print", + "cinema", + "email", + "gaming", + "retail_media", + "influencer", + "affiliate", + "product_placement" + ], + "enumDescriptions": { + "display": "Digital display advertising (banners, native, rich media) across web and app", + "olv": "Online video advertising outside CTV (pre-roll, outstream, in-app video)", + "social": "Social media platforms (Facebook, Instagram, TikTok, LinkedIn, etc.)", + "search": "Search engine advertising and search networks", + "ctv": "Connected TV and streaming on television screens", + "linear_tv": "Traditional broadcast and cable television", + "radio": "Traditional AM/FM radio broadcast", + "streaming_audio": "Digital audio streaming services (Spotify, Pandora, etc.)", + "podcast": "Podcast advertising (host-read or dynamically inserted)", + "dooh": "Digital out-of-home screens in public spaces", + "ooh": "Classic out-of-home (physical billboards, transit, etc.)", + "print": "Newspapers, magazines, and other print publications", + "cinema": "Movie theater advertising", + "email": "Email advertising and sponsored newsletter content", + "gaming": "In-game advertising across platforms", + "retail_media": "Retail media networks and commerce marketplaces (Amazon, Walmart, Instacart)", + "influencer": "Creator and influencer marketing partnerships", + "affiliate": "Affiliate networks, comparison sites, and performance-based partnerships", + "product_placement": "Product placement, branded content, and sponsorship integrations" + } + }, + "minItems": 1, + "description": "Filter by channel" + }, + "languages": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "Filter by BCP 47 language tags" + }, + "countries": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "Filter by ISO 3166-1 alpha-2 country codes" + }, + "pagination": { + "title": "Pagination Request", + "description": "Standard cursor-based pagination parameters for list operations", + "type": "object", + "properties": { + "max_results": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 50, + "description": "Maximum number of items to return per page" + }, + "cursor": { + "type": "string", + "description": "Opaque cursor from a previous response to fetch the next page" + } + }, + "additionalProperties": false + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true, + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.779Z", + "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/dist/schemas/3.0.0-beta.4/bundled/content-standards/list-content-standards-response.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/list-content-standards-response.json new file mode 100644 index 000000000..6259af357 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/list-content-standards-response.json @@ -0,0 +1,2028 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/list-content-standards-response.json", + "title": "List Content Standards Response", + "description": "Response payload with list of content standards configurations", + "type": "object", + "oneOf": [ + { + "type": "object", + "description": "Success response - returns array of content standards", + "properties": { + "standards": { + "type": "array", + "items": { + "title": "Content Standards", + "description": "A content standards configuration defining brand safety and suitability policies. Standards are scoped by brand, geography, and channel. Multiple standards can be active simultaneously for different scopes.", + "type": "object", + "properties": { + "standards_id": { + "type": "string", + "description": "Unique identifier for this standards configuration" + }, + "name": { + "type": "string", + "description": "Human-readable name for this standards configuration" + }, + "countries_all": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "ISO 3166-1 alpha-2 country codes. Standards apply in ALL listed countries (AND logic)." + }, + "channels_any": { + "type": "array", + "items": { + "title": "Media Channel", + "description": "Standardized advertising media channels describing how buyers allocate budget. Channels are planning abstractions, not technical substrates. See the Media Channel Taxonomy specification for detailed definitions.", + "type": "string", + "enum": [ + "display", + "olv", + "social", + "search", + "ctv", + "linear_tv", + "radio", + "streaming_audio", + "podcast", + "dooh", + "ooh", + "print", + "cinema", + "email", + "gaming", + "retail_media", + "influencer", + "affiliate", + "product_placement" + ], + "enumDescriptions": { + "display": "Digital display advertising (banners, native, rich media) across web and app", + "olv": "Online video advertising outside CTV (pre-roll, outstream, in-app video)", + "social": "Social media platforms (Facebook, Instagram, TikTok, LinkedIn, etc.)", + "search": "Search engine advertising and search networks", + "ctv": "Connected TV and streaming on television screens", + "linear_tv": "Traditional broadcast and cable television", + "radio": "Traditional AM/FM radio broadcast", + "streaming_audio": "Digital audio streaming services (Spotify, Pandora, etc.)", + "podcast": "Podcast advertising (host-read or dynamically inserted)", + "dooh": "Digital out-of-home screens in public spaces", + "ooh": "Classic out-of-home (physical billboards, transit, etc.)", + "print": "Newspapers, magazines, and other print publications", + "cinema": "Movie theater advertising", + "email": "Email advertising and sponsored newsletter content", + "gaming": "In-game advertising across platforms", + "retail_media": "Retail media networks and commerce marketplaces (Amazon, Walmart, Instacart)", + "influencer": "Creator and influencer marketing partnerships", + "affiliate": "Affiliate networks, comparison sites, and performance-based partnerships", + "product_placement": "Product placement, branded content, and sponsorship integrations" + } + }, + "minItems": 1, + "description": "Advertising channels. Standards apply to ANY of the listed channels (OR logic)." + }, + "languages_any": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "BCP 47 language tags (e.g., 'en', 'de', 'fr'). Standards apply to content in ANY of these languages (OR logic). Content in unlisted languages is not covered by these standards." + }, + "policy": { + "type": "string", + "description": "Natural language policy describing acceptable and unacceptable content contexts. Used by LLMs and human reviewers to make judgments." + }, + "calibration_exemplars": { + "type": "object", + "description": "Training/test set to calibrate policy interpretation. Provides concrete examples of pass/fail decisions.", + "properties": { + "pass": { + "type": "array", + "items": { + "title": "Artifact", + "description": "Content artifact for safety and suitability evaluation. An artifact represents content adjacent to an ad placement - a news article, podcast segment, video chapter, or social post. Artifacts are collections of assets (text, images, video, audio) plus metadata and signals.", + "type": "object", + "properties": { + "property_id": { + "title": "Identifier", + "description": "Identifier for the property where this artifact appears", + "type": "object", + "properties": { + "type": { + "title": "Property Identifier Types", + "description": "Type of identifier", + "type": "string", + "enum": [ + "domain", + "subdomain", + "network_id", + "ios_bundle", + "android_package", + "apple_app_store_id", + "google_play_id", + "roku_store_id", + "fire_tv_asin", + "samsung_app_id", + "apple_tv_bundle", + "bundle_id", + "venue_id", + "screen_id", + "openooh_venue_type", + "rss_url", + "apple_podcast_id", + "spotify_show_id", + "podcast_guid" + ], + "examples": [ + "domain", + "ios_bundle", + "venue_id", + "apple_podcast_id" + ] + }, + "value": { + "type": "string", + "description": "The identifier value. For domain type: 'example.com' matches base domain plus www and m subdomains; 'edition.example.com' matches that specific subdomain; '*.example.com' matches ALL subdomains but NOT base domain" + } + }, + "required": [ + "type", + "value" + ], + "additionalProperties": false + }, + "artifact_id": { + "type": "string", + "description": "Identifier for this artifact within the property. The property owner defines the scheme (e.g., 'article_12345', 'episode_42_segment_3', 'post_abc123')." + }, + "variant_id": { + "type": "string", + "description": "Identifies a specific variant of this artifact. Use for A/B tests, translations, or temporal versions. Examples: 'en', 'es-MX', 'v2', 'headline_test_b'. The combination of artifact_id + variant_id must be unique." + }, + "format_id": { + "title": "Format ID", + "description": "Optional reference to a format definition. Uses the same format registry as creative formats.", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "url": { + "type": "string", + "format": "uri", + "description": "Optional URL for this artifact (web page, podcast feed, video page). Not all artifacts have URLs (e.g., Instagram content, podcast segments, TV scenes)." + }, + "published_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was published (ISO 8601 format)" + }, + "last_update_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was last modified (ISO 8601 format)" + }, + "assets": { + "type": "array", + "description": "Artifact assets in document flow order - text blocks, images, video, audio", + "items": { + "oneOf": [ + { + "type": "object", + "description": "Text block (paragraph, heading, etc.)", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "role": { + "type": "string", + "enum": [ + "title", + "paragraph", + "heading", + "caption", + "quote", + "list_item", + "description" + ], + "description": "Role of this text in the document. Use 'title' for the main artifact title, 'description' for summaries." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for this text (e.g., 'en', 'es-MX'). Useful when artifact contains mixed-language content." + }, + "heading_level": { + "type": "integer", + "minimum": 1, + "maximum": 6, + "description": "Heading level (1-6), only for role=heading" + } + }, + "required": [ + "type", + "content" + ] + }, + { + "type": "object", + "description": "Image asset", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Image URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "alt_text": { + "type": "string", + "description": "Alt text or image description" + }, + "caption": { + "type": "string", + "description": "Image caption" + }, + "width": { + "type": "integer", + "description": "Image width in pixels" + }, + "height": { + "type": "integer", + "description": "Image height in pixels" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Video asset", + "properties": { + "type": { + "type": "string", + "const": "video" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Video URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Video duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Video transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "subtitles", + "closed_captions", + "dub", + "generated" + ], + "description": "How the transcript was generated" + }, + "thumbnail_url": { + "type": "string", + "format": "uri", + "description": "Video thumbnail URL" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Audio asset", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Audio URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Audio duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Audio transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "closed_captions", + "generated" + ], + "description": "How the transcript was generated" + } + }, + "required": [ + "type", + "url" + ] + } + ] + } + }, + "metadata": { + "type": "object", + "description": "Rich metadata extracted from the artifact", + "properties": { + "canonical": { + "type": "string", + "format": "uri", + "description": "Canonical URL" + }, + "author": { + "type": "string", + "description": "Artifact author name" + }, + "keywords": { + "type": "string", + "description": "Artifact keywords" + }, + "open_graph": { + "type": "object", + "description": "Open Graph protocol metadata", + "additionalProperties": true + }, + "twitter_card": { + "type": "object", + "description": "Twitter Card metadata", + "additionalProperties": true + }, + "json_ld": { + "type": "array", + "description": "JSON-LD structured data (schema.org)", + "items": { + "type": "object" + } + } + }, + "additionalProperties": true + }, + "identifiers": { + "type": "object", + "description": "Platform-specific identifiers for this artifact", + "properties": { + "apple_podcast_id": { + "type": "string", + "description": "Apple Podcasts ID" + }, + "spotify_show_id": { + "type": "string", + "description": "Spotify show ID" + }, + "podcast_guid": { + "type": "string", + "description": "Podcast GUID (from RSS feed)" + }, + "youtube_video_id": { + "type": "string", + "description": "YouTube video ID" + }, + "rss_url": { + "type": "string", + "format": "uri", + "description": "RSS feed URL" + } + }, + "additionalProperties": true + } + }, + "required": [ + "property_id", + "artifact_id", + "assets" + ], + "additionalProperties": true, + "$defs": { + "asset_access": { + "type": "object", + "description": "Authentication for accessing secured asset URLs", + "oneOf": [ + { + "type": "object", + "description": "Bearer token authentication", + "properties": { + "method": { + "type": "string", + "const": "bearer_token" + }, + "token": { + "type": "string", + "description": "OAuth2 bearer token for Authorization header" + } + }, + "required": [ + "method", + "token" + ] + }, + { + "type": "object", + "description": "Service account authentication (GCP, AWS)", + "properties": { + "method": { + "type": "string", + "const": "service_account" + }, + "provider": { + "type": "string", + "enum": [ + "gcp", + "aws" + ], + "description": "Cloud provider" + }, + "credentials": { + "type": "object", + "description": "Service account credentials", + "additionalProperties": true + } + }, + "required": [ + "method", + "provider" + ] + }, + { + "type": "object", + "description": "Pre-signed URL (credentials embedded in URL)", + "properties": { + "method": { + "type": "string", + "const": "signed_url" + } + }, + "required": [ + "method" + ] + } + ] + } + } + }, + "description": "Artifacts that pass the content standards" + }, + "fail": { + "type": "array", + "items": { + "title": "Artifact", + "description": "Content artifact for safety and suitability evaluation. An artifact represents content adjacent to an ad placement - a news article, podcast segment, video chapter, or social post. Artifacts are collections of assets (text, images, video, audio) plus metadata and signals.", + "type": "object", + "properties": { + "property_id": { + "title": "Identifier", + "description": "Identifier for the property where this artifact appears", + "type": "object", + "properties": { + "type": { + "title": "Property Identifier Types", + "description": "Type of identifier", + "type": "string", + "enum": [ + "domain", + "subdomain", + "network_id", + "ios_bundle", + "android_package", + "apple_app_store_id", + "google_play_id", + "roku_store_id", + "fire_tv_asin", + "samsung_app_id", + "apple_tv_bundle", + "bundle_id", + "venue_id", + "screen_id", + "openooh_venue_type", + "rss_url", + "apple_podcast_id", + "spotify_show_id", + "podcast_guid" + ], + "examples": [ + "domain", + "ios_bundle", + "venue_id", + "apple_podcast_id" + ] + }, + "value": { + "type": "string", + "description": "The identifier value. For domain type: 'example.com' matches base domain plus www and m subdomains; 'edition.example.com' matches that specific subdomain; '*.example.com' matches ALL subdomains but NOT base domain" + } + }, + "required": [ + "type", + "value" + ], + "additionalProperties": false + }, + "artifact_id": { + "type": "string", + "description": "Identifier for this artifact within the property. The property owner defines the scheme (e.g., 'article_12345', 'episode_42_segment_3', 'post_abc123')." + }, + "variant_id": { + "type": "string", + "description": "Identifies a specific variant of this artifact. Use for A/B tests, translations, or temporal versions. Examples: 'en', 'es-MX', 'v2', 'headline_test_b'. The combination of artifact_id + variant_id must be unique." + }, + "format_id": { + "title": "Format ID", + "description": "Optional reference to a format definition. Uses the same format registry as creative formats.", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "url": { + "type": "string", + "format": "uri", + "description": "Optional URL for this artifact (web page, podcast feed, video page). Not all artifacts have URLs (e.g., Instagram content, podcast segments, TV scenes)." + }, + "published_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was published (ISO 8601 format)" + }, + "last_update_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was last modified (ISO 8601 format)" + }, + "assets": { + "type": "array", + "description": "Artifact assets in document flow order - text blocks, images, video, audio", + "items": { + "oneOf": [ + { + "type": "object", + "description": "Text block (paragraph, heading, etc.)", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "role": { + "type": "string", + "enum": [ + "title", + "paragraph", + "heading", + "caption", + "quote", + "list_item", + "description" + ], + "description": "Role of this text in the document. Use 'title' for the main artifact title, 'description' for summaries." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for this text (e.g., 'en', 'es-MX'). Useful when artifact contains mixed-language content." + }, + "heading_level": { + "type": "integer", + "minimum": 1, + "maximum": 6, + "description": "Heading level (1-6), only for role=heading" + } + }, + "required": [ + "type", + "content" + ] + }, + { + "type": "object", + "description": "Image asset", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Image URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "alt_text": { + "type": "string", + "description": "Alt text or image description" + }, + "caption": { + "type": "string", + "description": "Image caption" + }, + "width": { + "type": "integer", + "description": "Image width in pixels" + }, + "height": { + "type": "integer", + "description": "Image height in pixels" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Video asset", + "properties": { + "type": { + "type": "string", + "const": "video" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Video URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Video duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Video transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "subtitles", + "closed_captions", + "dub", + "generated" + ], + "description": "How the transcript was generated" + }, + "thumbnail_url": { + "type": "string", + "format": "uri", + "description": "Video thumbnail URL" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Audio asset", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Audio URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Audio duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Audio transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "closed_captions", + "generated" + ], + "description": "How the transcript was generated" + } + }, + "required": [ + "type", + "url" + ] + } + ] + } + }, + "metadata": { + "type": "object", + "description": "Rich metadata extracted from the artifact", + "properties": { + "canonical": { + "type": "string", + "format": "uri", + "description": "Canonical URL" + }, + "author": { + "type": "string", + "description": "Artifact author name" + }, + "keywords": { + "type": "string", + "description": "Artifact keywords" + }, + "open_graph": { + "type": "object", + "description": "Open Graph protocol metadata", + "additionalProperties": true + }, + "twitter_card": { + "type": "object", + "description": "Twitter Card metadata", + "additionalProperties": true + }, + "json_ld": { + "type": "array", + "description": "JSON-LD structured data (schema.org)", + "items": { + "type": "object" + } + } + }, + "additionalProperties": true + }, + "identifiers": { + "type": "object", + "description": "Platform-specific identifiers for this artifact", + "properties": { + "apple_podcast_id": { + "type": "string", + "description": "Apple Podcasts ID" + }, + "spotify_show_id": { + "type": "string", + "description": "Spotify show ID" + }, + "podcast_guid": { + "type": "string", + "description": "Podcast GUID (from RSS feed)" + }, + "youtube_video_id": { + "type": "string", + "description": "YouTube video ID" + }, + "rss_url": { + "type": "string", + "format": "uri", + "description": "RSS feed URL" + } + }, + "additionalProperties": true + } + }, + "required": [ + "property_id", + "artifact_id", + "assets" + ], + "additionalProperties": true, + "$defs": { + "asset_access": { + "type": "object", + "description": "Authentication for accessing secured asset URLs", + "oneOf": [ + { + "type": "object", + "description": "Bearer token authentication", + "properties": { + "method": { + "type": "string", + "const": "bearer_token" + }, + "token": { + "type": "string", + "description": "OAuth2 bearer token for Authorization header" + } + }, + "required": [ + "method", + "token" + ] + }, + { + "type": "object", + "description": "Service account authentication (GCP, AWS)", + "properties": { + "method": { + "type": "string", + "const": "service_account" + }, + "provider": { + "type": "string", + "enum": [ + "gcp", + "aws" + ], + "description": "Cloud provider" + }, + "credentials": { + "type": "object", + "description": "Service account credentials", + "additionalProperties": true + } + }, + "required": [ + "method", + "provider" + ] + }, + { + "type": "object", + "description": "Pre-signed URL (credentials embedded in URL)", + "properties": { + "method": { + "type": "string", + "const": "signed_url" + } + }, + "required": [ + "method" + ] + } + ] + } + } + }, + "description": "Artifacts that fail the content standards" + } + } + }, + "pricing_options": { + "type": "array", + "description": "Pricing options for this content standards service. The buyer passes the selected pricing_option_id in report_usage for billing verification.", + "items": { + "title": "Pricing Option", + "description": "A pricing model option offered by a publisher for a product. Discriminated by pricing_model field. If fixed_price is present, it's fixed pricing. If absent, it's auction-based (floor_price and price_guidance optional). Bid-based auction models may also include max_bid as a boolean signal to interpret bid_price as a buyer ceiling instead of an exact honored price.", + "oneOf": [ + { + "title": "CPM Pricing Option", + "description": "Cost Per Mille (cost per 1,000 impressions) pricing. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "cpm", + "description": "Cost per 1,000 impressions" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per unit. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "max_bid": { + "type": "boolean", + "description": "When true, bid_price is interpreted as the buyer's maximum willingness to pay (ceiling) rather than an exact price. Sellers may optimize actual clearing prices between floor_price and bid_price based on delivery pacing. When false or absent, bid_price (if provided) is the exact bid/price to honor.", + "default": false + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency" + ], + "additionalProperties": true + }, + { + "title": "vCPM Pricing Option", + "description": "Viewable Cost Per Mille (cost per 1,000 viewable impressions) pricing - MRC viewability standard. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "vcpm", + "description": "Cost per 1,000 viewable impressions (MRC standard)" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per unit. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "max_bid": { + "type": "boolean", + "description": "When true, bid_price is interpreted as the buyer's maximum willingness to pay (ceiling) rather than an exact price. Sellers may optimize actual clearing prices between floor_price and bid_price based on delivery pacing. When false or absent, bid_price (if provided) is the exact bid/price to honor.", + "default": false + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency" + ], + "additionalProperties": true + }, + { + "title": "CPC Pricing Option", + "description": "Cost Per Click pricing. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "cpc", + "description": "Cost per click" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per click. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "max_bid": { + "type": "boolean", + "description": "When true, bid_price is interpreted as the buyer's maximum willingness to pay (ceiling) rather than an exact price. Sellers may optimize actual clearing prices between floor_price and bid_price based on delivery pacing. When false or absent, bid_price (if provided) is the exact bid/price to honor.", + "default": false + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency" + ], + "additionalProperties": true + }, + { + "title": "CPCV Pricing Option", + "description": "Cost Per Completed View (100% video/audio completion) pricing. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "cpcv", + "description": "Cost per completed view (100% completion)" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per completed view. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "max_bid": { + "type": "boolean", + "description": "When true, bid_price is interpreted as the buyer's maximum willingness to pay (ceiling) rather than an exact price. Sellers may optimize actual clearing prices between floor_price and bid_price based on delivery pacing. When false or absent, bid_price (if provided) is the exact bid/price to honor.", + "default": false + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency" + ], + "additionalProperties": true + }, + { + "title": "CPV Pricing Option", + "description": "Cost Per View (at publisher-defined threshold) pricing for video/audio. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "cpv", + "description": "Cost per view at threshold" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per view. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "max_bid": { + "type": "boolean", + "description": "When true, bid_price is interpreted as the buyer's maximum willingness to pay (ceiling) rather than an exact price. Sellers may optimize actual clearing prices between floor_price and bid_price based on delivery pacing. When false or absent, bid_price (if provided) is the exact bid/price to honor.", + "default": false + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "parameters": { + "type": "object", + "description": "CPV-specific parameters defining the view threshold", + "properties": { + "view_threshold": { + "oneOf": [ + { + "type": "number", + "description": "Percentage completion threshold (0.0 to 1.0, e.g., 0.5 = 50%)", + "minimum": 0, + "maximum": 1 + }, + { + "type": "object", + "description": "Time-based view threshold", + "properties": { + "duration_seconds": { + "type": "integer", + "description": "Seconds of viewing required", + "minimum": 1 + } + }, + "required": [ + "duration_seconds" + ], + "additionalProperties": true + } + ] + } + }, + "required": [ + "view_threshold" + ], + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency", + "parameters" + ], + "additionalProperties": true + }, + { + "title": "CPP Pricing Option", + "description": "Cost Per Point (Gross Rating Point) pricing for TV and audio campaigns. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "cpp", + "description": "Cost per Gross Rating Point" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per rating point. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "parameters": { + "type": "object", + "description": "CPP-specific parameters for demographic targeting", + "properties": { + "demographic_system": { + "title": "Demographic System", + "description": "Measurement system for the demographic field. Defaults to nielsen when omitted.", + "type": "string", + "enum": [ + "nielsen", + "barb", + "agf", + "oztam", + "mediametrie", + "custom" + ], + "enumDescriptions": { + "nielsen": "Nielsen notation. Prefix: P(ersons), M(en), W(omen), A(dults), C(hildren), T(eens) + age range. Examples: P18-49, M25-54, W35+", + "barb": "BARB (UK). NRS social grade + age bands. Examples: ABC1 Adults, 16-34, Adults", + "agf": "AGF Videoforschung (Germany). Erwachsene notation + age bands. Examples: E 14-49, E 14+", + "oztam": "OzTAM (Australia). Age/gender bands, 4+ measurement universe", + "mediametrie": "Mediametrie (France). Named segments + age bands", + "custom": "Publisher-defined demographic notation" + } + }, + "demographic": { + "type": "string", + "description": "Target demographic code within the specified demographic_system (e.g., P18-49 for Nielsen, ABC1 Adults for BARB)" + }, + "min_points": { + "type": "number", + "description": "Minimum GRPs/TRPs required", + "minimum": 0 + } + }, + "required": [ + "demographic" + ], + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency", + "parameters" + ], + "additionalProperties": true + }, + { + "title": "CPA Pricing Option", + "description": "Cost Per Acquisition pricing. Advertiser pays a fixed price when a specified conversion event occurs. The event_type field declares which event triggers billing (e.g., purchase, lead, app_install).", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "cpa", + "description": "Cost per acquisition (conversion event)" + }, + "event_type": { + "allOf": [ + { + "title": "Event Type", + "description": "Standard marketing event types for event logging, aligned with IAB ECAPI", + "type": "string", + "enum": [ + "page_view", + "view_content", + "select_content", + "select_item", + "search", + "share", + "add_to_cart", + "remove_from_cart", + "viewed_cart", + "add_to_wishlist", + "initiate_checkout", + "add_payment_info", + "purchase", + "refund", + "lead", + "qualify_lead", + "close_convert_lead", + "disqualify_lead", + "complete_registration", + "subscribe", + "start_trial", + "app_install", + "app_launch", + "contact", + "schedule", + "donate", + "submit_application", + "custom" + ], + "enumDescriptions": { + "page_view": "User viewed a page", + "view_content": "User viewed specific content (product, article, etc.)", + "select_content": "User selected or clicked on content (article, video, etc.)", + "select_item": "User selected a specific product or item from a list", + "search": "User performed a search", + "share": "User shared content via social or messaging", + "add_to_cart": "User added an item to cart", + "remove_from_cart": "User removed an item from cart", + "viewed_cart": "User viewed their shopping cart", + "add_to_wishlist": "User added an item to a wishlist", + "initiate_checkout": "User started checkout process", + "add_payment_info": "User added payment information", + "purchase": "User completed a purchase", + "refund": "A purchase was fully or partially refunded (adjusts ROAS)", + "lead": "User expressed interest (form submission, signup, etc.)", + "qualify_lead": "Lead qualified by sales or scoring criteria", + "close_convert_lead": "Lead converted to a customer or closed deal", + "disqualify_lead": "Lead disqualified or marked as not viable", + "complete_registration": "User completed account registration", + "subscribe": "User subscribed to a service or newsletter", + "start_trial": "User started a free trial", + "app_install": "User installed an application", + "app_launch": "User launched an application", + "contact": "User initiated contact (call, message, etc.)", + "schedule": "User scheduled an appointment or event", + "donate": "User made a donation", + "submit_application": "User submitted an application (loan, job, etc.)", + "custom": "Custom event type (specify in custom_event_name)" + } + } + ], + "description": "The conversion event type that triggers billing (e.g., purchase, lead, app_install)" + }, + "custom_event_name": { + "type": "string", + "description": "Name of the custom event when event_type is 'custom'. Required when event_type is 'custom', ignored otherwise." + }, + "event_source_id": { + "type": "string", + "description": "When present, only events from this specific event source count toward billing. Allows different CPA rates for different sources (e.g., online vs in-store purchases). Must match an event source configured via sync_event_sources." + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Fixed price per acquisition in the specified currency", + "exclusiveMinimum": 0 + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "event_type", + "currency", + "fixed_price" + ], + "additionalProperties": true + }, + { + "title": "Flat Rate Pricing Option", + "description": "Flat rate pricing for DOOH, sponsorships, and time-based campaigns. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "flat_rate", + "description": "Fixed cost regardless of delivery volume" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Flat rate cost. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "parameters": { + "type": "object", + "description": "Flat rate parameters for DOOH and time-based campaigns", + "properties": { + "duration_hours": { + "type": "number", + "description": "Duration in hours for time-based pricing", + "minimum": 0 + }, + "sov_percentage": { + "type": "number", + "description": "Guaranteed share of voice (0-100)", + "minimum": 0, + "maximum": 100 + }, + "loop_duration_seconds": { + "type": "integer", + "description": "Duration of ad loop rotation in seconds", + "minimum": 1 + }, + "min_plays_per_hour": { + "type": "integer", + "description": "Minimum plays per hour", + "minimum": 0 + }, + "venue_package": { + "type": "string", + "description": "Named venue package identifier" + }, + "estimated_impressions": { + "type": "integer", + "description": "Estimated impressions (informational)", + "minimum": 0 + }, + "daypart": { + "type": "string", + "description": "Specific daypart for time-based pricing" + } + }, + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency" + ], + "additionalProperties": true + }, + { + "title": "Time-Based Pricing Option", + "description": "Cost per time unit (hour, day, week, or month) - rate scales with campaign duration. If fixed_price is present, it's fixed pricing. If absent, it's auction-based.", + "type": "object", + "properties": { + "pricing_option_id": { + "type": "string", + "description": "Unique identifier for this pricing option within the product" + }, + "pricing_model": { + "type": "string", + "const": "time", + "description": "Cost per time unit - rate scales with campaign duration" + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code", + "pattern": "^[A-Z]{3}$", + "examples": [ + "USD", + "EUR", + "GBP", + "JPY" + ] + }, + "fixed_price": { + "type": "number", + "description": "Cost per time unit. If present, this is fixed pricing. If absent, auction-based.", + "minimum": 0 + }, + "floor_price": { + "type": "number", + "description": "Minimum acceptable bid per time unit for auction pricing (mutually exclusive with fixed_price). Bids below this value will be rejected.", + "minimum": 0 + }, + "price_guidance": { + "description": "Pricing guidance for auction-based bidding. Helps buyers calibrate bids with historical percentiles.", + "title": "Price Guidance", + "type": "object", + "properties": { + "p25": { + "type": "number", + "description": "25th percentile of recent winning bids", + "minimum": 0 + }, + "p50": { + "type": "number", + "description": "Median of recent winning bids", + "minimum": 0 + }, + "p75": { + "type": "number", + "description": "75th percentile of recent winning bids", + "minimum": 0 + }, + "p90": { + "type": "number", + "description": "90th percentile of recent winning bids", + "minimum": 0 + } + }, + "additionalProperties": true + }, + "parameters": { + "type": "object", + "description": "Time-based pricing parameters", + "required": [ + "time_unit" + ], + "properties": { + "time_unit": { + "type": "string", + "enum": [ + "hour", + "day", + "week", + "month" + ], + "description": "The time unit for pricing. Total cost = fixed_price × number of time_units in the campaign flight." + }, + "min_duration": { + "type": "integer", + "minimum": 1, + "description": "Minimum booking duration in time_units" + }, + "max_duration": { + "type": "integer", + "minimum": 1, + "description": "Maximum booking duration in time_units. Must be >= min_duration when both are present." + } + }, + "additionalProperties": true + }, + "min_spend_per_package": { + "type": "number", + "description": "Minimum spend requirement per package using this pricing option, in the specified currency", + "minimum": 0 + } + }, + "required": [ + "pricing_option_id", + "pricing_model", + "currency", + "parameters" + ], + "additionalProperties": true + } + ] + }, + "minItems": 1 + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "standards_id" + ] + }, + "description": "Array of content standards configurations matching the filter criteria" + }, + "errors": { + "not": {}, + "description": "Field must not be present in success response" + }, + "pagination": { + "title": "Pagination Response", + "description": "Standard cursor-based pagination metadata for list responses", + "type": "object", + "properties": { + "has_more": { + "type": "boolean", + "description": "Whether more results are available beyond this page" + }, + "cursor": { + "type": "string", + "description": "Opaque cursor to pass in the next request to fetch the next page. Only present when has_more is true." + }, + "total_count": { + "type": "integer", + "minimum": 0, + "description": "Total number of items matching the query across all pages. Optional because not all backends can efficiently compute this." + } + }, + "required": [ + "has_more" + ], + "additionalProperties": false + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "standards" + ] + }, + { + "type": "object", + "description": "Error response", + "properties": { + "errors": { + "type": "array", + "items": { + "title": "Error", + "description": "Standard error structure for task-specific errors and warnings", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Error code for programmatic handling" + }, + "message": { + "type": "string", + "description": "Human-readable error message" + }, + "field": { + "type": "string", + "description": "Field path associated with the error (e.g., 'packages[0].targeting')" + }, + "suggestion": { + "type": "string", + "description": "Suggested fix for the error" + }, + "retry_after": { + "type": "number", + "description": "Seconds to wait before retrying the operation", + "minimum": 0 + }, + "details": { + "type": "object", + "description": "Additional task-specific error details", + "additionalProperties": true + } + }, + "required": [ + "code", + "message" + ], + "additionalProperties": true + } + }, + "standards": { + "not": {}, + "description": "Field must not be present in error response" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "errors" + ] + } + ], + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.781Z", + "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/dist/schemas/3.0.0-beta.4/bundled/content-standards/update-content-standards-request.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/update-content-standards-request.json new file mode 100644 index 000000000..0084dc602 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/update-content-standards-request.json @@ -0,0 +1,1055 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/update-content-standards-request.json", + "title": "Update Content Standards Request", + "description": "Request parameters for updating an existing content standards configuration. Creates a new version.", + "type": "object", + "properties": { + "standards_id": { + "type": "string", + "description": "ID of the standards configuration to update" + }, + "scope": { + "type": "object", + "description": "Updated scope for where this standards configuration applies", + "properties": { + "countries_all": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "ISO 3166-1 alpha-2 country codes. Standards apply in ALL listed countries (AND logic)." + }, + "channels_any": { + "type": "array", + "items": { + "title": "Media Channel", + "description": "Standardized advertising media channels describing how buyers allocate budget. Channels are planning abstractions, not technical substrates. See the Media Channel Taxonomy specification for detailed definitions.", + "type": "string", + "enum": [ + "display", + "olv", + "social", + "search", + "ctv", + "linear_tv", + "radio", + "streaming_audio", + "podcast", + "dooh", + "ooh", + "print", + "cinema", + "email", + "gaming", + "retail_media", + "influencer", + "affiliate", + "product_placement" + ], + "enumDescriptions": { + "display": "Digital display advertising (banners, native, rich media) across web and app", + "olv": "Online video advertising outside CTV (pre-roll, outstream, in-app video)", + "social": "Social media platforms (Facebook, Instagram, TikTok, LinkedIn, etc.)", + "search": "Search engine advertising and search networks", + "ctv": "Connected TV and streaming on television screens", + "linear_tv": "Traditional broadcast and cable television", + "radio": "Traditional AM/FM radio broadcast", + "streaming_audio": "Digital audio streaming services (Spotify, Pandora, etc.)", + "podcast": "Podcast advertising (host-read or dynamically inserted)", + "dooh": "Digital out-of-home screens in public spaces", + "ooh": "Classic out-of-home (physical billboards, transit, etc.)", + "print": "Newspapers, magazines, and other print publications", + "cinema": "Movie theater advertising", + "email": "Email advertising and sponsored newsletter content", + "gaming": "In-game advertising across platforms", + "retail_media": "Retail media networks and commerce marketplaces (Amazon, Walmart, Instacart)", + "influencer": "Creator and influencer marketing partnerships", + "affiliate": "Affiliate networks, comparison sites, and performance-based partnerships", + "product_placement": "Product placement, branded content, and sponsorship integrations" + } + }, + "minItems": 1, + "description": "Advertising channels. Standards apply to ANY of the listed channels (OR logic)." + }, + "languages_any": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "BCP 47 language tags (e.g., 'en', 'de', 'fr'). Standards apply to content in ANY of these languages (OR logic). Content in unlisted languages is not covered by these standards." + }, + "description": { + "type": "string", + "description": "Human-readable description of this scope" + } + } + }, + "policy": { + "type": "string", + "description": "Updated natural language policy describing acceptable and unacceptable content contexts." + }, + "calibration_exemplars": { + "type": "object", + "description": "Updated training/test set to calibrate policy interpretation. Use URL references for pages to be fetched and analyzed, or full artifacts for pre-extracted content.", + "properties": { + "pass": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "description": "URL reference - specific page to fetch and evaluate", + "properties": { + "type": { + "type": "string", + "const": "url", + "description": "Indicates this is a URL reference" + }, + "value": { + "type": "string", + "format": "uri", + "description": "Full URL to a specific page (e.g., 'https://espn.com/nba/story/_/id/12345/lakers-win')" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for content at this URL" + } + }, + "required": [ + "type", + "value" + ] + }, + { + "title": "Artifact", + "description": "Full artifact with pre-extracted content (text, images, video, audio)", + "type": "object", + "properties": { + "property_id": { + "title": "Identifier", + "description": "Identifier for the property where this artifact appears", + "type": "object", + "properties": { + "type": { + "title": "Property Identifier Types", + "description": "Type of identifier", + "type": "string", + "enum": [ + "domain", + "subdomain", + "network_id", + "ios_bundle", + "android_package", + "apple_app_store_id", + "google_play_id", + "roku_store_id", + "fire_tv_asin", + "samsung_app_id", + "apple_tv_bundle", + "bundle_id", + "venue_id", + "screen_id", + "openooh_venue_type", + "rss_url", + "apple_podcast_id", + "spotify_show_id", + "podcast_guid" + ], + "examples": [ + "domain", + "ios_bundle", + "venue_id", + "apple_podcast_id" + ] + }, + "value": { + "type": "string", + "description": "The identifier value. For domain type: 'example.com' matches base domain plus www and m subdomains; 'edition.example.com' matches that specific subdomain; '*.example.com' matches ALL subdomains but NOT base domain" + } + }, + "required": [ + "type", + "value" + ], + "additionalProperties": false + }, + "artifact_id": { + "type": "string", + "description": "Identifier for this artifact within the property. The property owner defines the scheme (e.g., 'article_12345', 'episode_42_segment_3', 'post_abc123')." + }, + "variant_id": { + "type": "string", + "description": "Identifies a specific variant of this artifact. Use for A/B tests, translations, or temporal versions. Examples: 'en', 'es-MX', 'v2', 'headline_test_b'. The combination of artifact_id + variant_id must be unique." + }, + "format_id": { + "title": "Format ID", + "description": "Optional reference to a format definition. Uses the same format registry as creative formats.", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "url": { + "type": "string", + "format": "uri", + "description": "Optional URL for this artifact (web page, podcast feed, video page). Not all artifacts have URLs (e.g., Instagram content, podcast segments, TV scenes)." + }, + "published_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was published (ISO 8601 format)" + }, + "last_update_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was last modified (ISO 8601 format)" + }, + "assets": { + "type": "array", + "description": "Artifact assets in document flow order - text blocks, images, video, audio", + "items": { + "oneOf": [ + { + "type": "object", + "description": "Text block (paragraph, heading, etc.)", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "role": { + "type": "string", + "enum": [ + "title", + "paragraph", + "heading", + "caption", + "quote", + "list_item", + "description" + ], + "description": "Role of this text in the document. Use 'title' for the main artifact title, 'description' for summaries." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for this text (e.g., 'en', 'es-MX'). Useful when artifact contains mixed-language content." + }, + "heading_level": { + "type": "integer", + "minimum": 1, + "maximum": 6, + "description": "Heading level (1-6), only for role=heading" + } + }, + "required": [ + "type", + "content" + ] + }, + { + "type": "object", + "description": "Image asset", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Image URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "alt_text": { + "type": "string", + "description": "Alt text or image description" + }, + "caption": { + "type": "string", + "description": "Image caption" + }, + "width": { + "type": "integer", + "description": "Image width in pixels" + }, + "height": { + "type": "integer", + "description": "Image height in pixels" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Video asset", + "properties": { + "type": { + "type": "string", + "const": "video" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Video URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Video duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Video transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "subtitles", + "closed_captions", + "dub", + "generated" + ], + "description": "How the transcript was generated" + }, + "thumbnail_url": { + "type": "string", + "format": "uri", + "description": "Video thumbnail URL" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Audio asset", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Audio URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Audio duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Audio transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "closed_captions", + "generated" + ], + "description": "How the transcript was generated" + } + }, + "required": [ + "type", + "url" + ] + } + ] + } + }, + "metadata": { + "type": "object", + "description": "Rich metadata extracted from the artifact", + "properties": { + "canonical": { + "type": "string", + "format": "uri", + "description": "Canonical URL" + }, + "author": { + "type": "string", + "description": "Artifact author name" + }, + "keywords": { + "type": "string", + "description": "Artifact keywords" + }, + "open_graph": { + "type": "object", + "description": "Open Graph protocol metadata", + "additionalProperties": true + }, + "twitter_card": { + "type": "object", + "description": "Twitter Card metadata", + "additionalProperties": true + }, + "json_ld": { + "type": "array", + "description": "JSON-LD structured data (schema.org)", + "items": { + "type": "object" + } + } + }, + "additionalProperties": true + }, + "identifiers": { + "type": "object", + "description": "Platform-specific identifiers for this artifact", + "properties": { + "apple_podcast_id": { + "type": "string", + "description": "Apple Podcasts ID" + }, + "spotify_show_id": { + "type": "string", + "description": "Spotify show ID" + }, + "podcast_guid": { + "type": "string", + "description": "Podcast GUID (from RSS feed)" + }, + "youtube_video_id": { + "type": "string", + "description": "YouTube video ID" + }, + "rss_url": { + "type": "string", + "format": "uri", + "description": "RSS feed URL" + } + }, + "additionalProperties": true + } + }, + "required": [ + "property_id", + "artifact_id", + "assets" + ], + "additionalProperties": true, + "$defs": { + "asset_access": { + "type": "object", + "description": "Authentication for accessing secured asset URLs", + "oneOf": [ + { + "type": "object", + "description": "Bearer token authentication", + "properties": { + "method": { + "type": "string", + "const": "bearer_token" + }, + "token": { + "type": "string", + "description": "OAuth2 bearer token for Authorization header" + } + }, + "required": [ + "method", + "token" + ] + }, + { + "type": "object", + "description": "Service account authentication (GCP, AWS)", + "properties": { + "method": { + "type": "string", + "const": "service_account" + }, + "provider": { + "type": "string", + "enum": [ + "gcp", + "aws" + ], + "description": "Cloud provider" + }, + "credentials": { + "type": "object", + "description": "Service account credentials", + "additionalProperties": true + } + }, + "required": [ + "method", + "provider" + ] + }, + { + "type": "object", + "description": "Pre-signed URL (credentials embedded in URL)", + "properties": { + "method": { + "type": "string", + "const": "signed_url" + } + }, + "required": [ + "method" + ] + } + ] + } + } + } + ] + }, + "description": "Content that passes the standards" + }, + "fail": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "description": "URL reference - specific page to fetch and evaluate", + "properties": { + "type": { + "type": "string", + "const": "url", + "description": "Indicates this is a URL reference" + }, + "value": { + "type": "string", + "format": "uri", + "description": "Full URL to a specific page (e.g., 'https://news.example.com/controversial-article')" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for content at this URL" + } + }, + "required": [ + "type", + "value" + ] + }, + { + "title": "Artifact", + "description": "Full artifact with pre-extracted content (text, images, video, audio)", + "type": "object", + "properties": { + "property_id": { + "title": "Identifier", + "description": "Identifier for the property where this artifact appears", + "type": "object", + "properties": { + "type": { + "title": "Property Identifier Types", + "description": "Type of identifier", + "type": "string", + "enum": [ + "domain", + "subdomain", + "network_id", + "ios_bundle", + "android_package", + "apple_app_store_id", + "google_play_id", + "roku_store_id", + "fire_tv_asin", + "samsung_app_id", + "apple_tv_bundle", + "bundle_id", + "venue_id", + "screen_id", + "openooh_venue_type", + "rss_url", + "apple_podcast_id", + "spotify_show_id", + "podcast_guid" + ], + "examples": [ + "domain", + "ios_bundle", + "venue_id", + "apple_podcast_id" + ] + }, + "value": { + "type": "string", + "description": "The identifier value. For domain type: 'example.com' matches base domain plus www and m subdomains; 'edition.example.com' matches that specific subdomain; '*.example.com' matches ALL subdomains but NOT base domain" + } + }, + "required": [ + "type", + "value" + ], + "additionalProperties": false + }, + "artifact_id": { + "type": "string", + "description": "Identifier for this artifact within the property. The property owner defines the scheme (e.g., 'article_12345', 'episode_42_segment_3', 'post_abc123')." + }, + "variant_id": { + "type": "string", + "description": "Identifies a specific variant of this artifact. Use for A/B tests, translations, or temporal versions. Examples: 'en', 'es-MX', 'v2', 'headline_test_b'. The combination of artifact_id + variant_id must be unique." + }, + "format_id": { + "title": "Format ID", + "description": "Optional reference to a format definition. Uses the same format registry as creative formats.", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "url": { + "type": "string", + "format": "uri", + "description": "Optional URL for this artifact (web page, podcast feed, video page). Not all artifacts have URLs (e.g., Instagram content, podcast segments, TV scenes)." + }, + "published_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was published (ISO 8601 format)" + }, + "last_update_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was last modified (ISO 8601 format)" + }, + "assets": { + "type": "array", + "description": "Artifact assets in document flow order - text blocks, images, video, audio", + "items": { + "oneOf": [ + { + "type": "object", + "description": "Text block (paragraph, heading, etc.)", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "role": { + "type": "string", + "enum": [ + "title", + "paragraph", + "heading", + "caption", + "quote", + "list_item", + "description" + ], + "description": "Role of this text in the document. Use 'title' for the main artifact title, 'description' for summaries." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for this text (e.g., 'en', 'es-MX'). Useful when artifact contains mixed-language content." + }, + "heading_level": { + "type": "integer", + "minimum": 1, + "maximum": 6, + "description": "Heading level (1-6), only for role=heading" + } + }, + "required": [ + "type", + "content" + ] + }, + { + "type": "object", + "description": "Image asset", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Image URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "alt_text": { + "type": "string", + "description": "Alt text or image description" + }, + "caption": { + "type": "string", + "description": "Image caption" + }, + "width": { + "type": "integer", + "description": "Image width in pixels" + }, + "height": { + "type": "integer", + "description": "Image height in pixels" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Video asset", + "properties": { + "type": { + "type": "string", + "const": "video" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Video URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Video duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Video transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "subtitles", + "closed_captions", + "dub", + "generated" + ], + "description": "How the transcript was generated" + }, + "thumbnail_url": { + "type": "string", + "format": "uri", + "description": "Video thumbnail URL" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Audio asset", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Audio URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Audio duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Audio transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "closed_captions", + "generated" + ], + "description": "How the transcript was generated" + } + }, + "required": [ + "type", + "url" + ] + } + ] + } + }, + "metadata": { + "type": "object", + "description": "Rich metadata extracted from the artifact", + "properties": { + "canonical": { + "type": "string", + "format": "uri", + "description": "Canonical URL" + }, + "author": { + "type": "string", + "description": "Artifact author name" + }, + "keywords": { + "type": "string", + "description": "Artifact keywords" + }, + "open_graph": { + "type": "object", + "description": "Open Graph protocol metadata", + "additionalProperties": true + }, + "twitter_card": { + "type": "object", + "description": "Twitter Card metadata", + "additionalProperties": true + }, + "json_ld": { + "type": "array", + "description": "JSON-LD structured data (schema.org)", + "items": { + "type": "object" + } + } + }, + "additionalProperties": true + }, + "identifiers": { + "type": "object", + "description": "Platform-specific identifiers for this artifact", + "properties": { + "apple_podcast_id": { + "type": "string", + "description": "Apple Podcasts ID" + }, + "spotify_show_id": { + "type": "string", + "description": "Spotify show ID" + }, + "podcast_guid": { + "type": "string", + "description": "Podcast GUID (from RSS feed)" + }, + "youtube_video_id": { + "type": "string", + "description": "YouTube video ID" + }, + "rss_url": { + "type": "string", + "format": "uri", + "description": "RSS feed URL" + } + }, + "additionalProperties": true + } + }, + "required": [ + "property_id", + "artifact_id", + "assets" + ], + "additionalProperties": true, + "$defs": { + "asset_access": { + "type": "object", + "description": "Authentication for accessing secured asset URLs", + "oneOf": [ + { + "type": "object", + "description": "Bearer token authentication", + "properties": { + "method": { + "type": "string", + "const": "bearer_token" + }, + "token": { + "type": "string", + "description": "OAuth2 bearer token for Authorization header" + } + }, + "required": [ + "method", + "token" + ] + }, + { + "type": "object", + "description": "Service account authentication (GCP, AWS)", + "properties": { + "method": { + "type": "string", + "const": "service_account" + }, + "provider": { + "type": "string", + "enum": [ + "gcp", + "aws" + ], + "description": "Cloud provider" + }, + "credentials": { + "type": "object", + "description": "Service account credentials", + "additionalProperties": true + } + }, + "required": [ + "method", + "provider" + ] + }, + { + "type": "object", + "description": "Pre-signed URL (credentials embedded in URL)", + "properties": { + "method": { + "type": "string", + "const": "signed_url" + } + }, + "required": [ + "method" + ] + } + ] + } + } + } + ] + }, + "description": "Content that fails the standards" + } + } + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "standards_id" + ], + "additionalProperties": true, + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.782Z", + "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/dist/schemas/3.0.0-beta.4/bundled/content-standards/update-content-standards-response.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/update-content-standards-response.json new file mode 100644 index 000000000..1a2c1c9fc --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/update-content-standards-response.json @@ -0,0 +1,76 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/update-content-standards-response.json", + "title": "Update Content Standards Response", + "description": "Response from updating a content standards configuration", + "type": "object", + "properties": { + "standards_id": { + "type": "string", + "description": "ID of the updated standards configuration" + }, + "errors": { + "type": "array", + "items": { + "title": "Error", + "description": "Standard error structure for task-specific errors and warnings", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Error code for programmatic handling" + }, + "message": { + "type": "string", + "description": "Human-readable error message" + }, + "field": { + "type": "string", + "description": "Field path associated with the error (e.g., 'packages[0].targeting')" + }, + "suggestion": { + "type": "string", + "description": "Suggested fix for the error" + }, + "retry_after": { + "type": "number", + "description": "Seconds to wait before retrying the operation", + "minimum": 0 + }, + "details": { + "type": "object", + "description": "Additional task-specific error details", + "additionalProperties": true + } + }, + "required": [ + "code", + "message" + ], + "additionalProperties": true + }, + "description": "Errors that occurred during the update" + }, + "conflicting_standards_id": { + "type": "string", + "description": "If scope change conflicts with another configuration, the ID of the conflicting standards" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true, + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.783Z", + "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/dist/schemas/3.0.0-beta.4/bundled/content-standards/validate-content-delivery-request.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/validate-content-delivery-request.json new file mode 100644 index 000000000..f6486ab4c --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/validate-content-delivery-request.json @@ -0,0 +1,531 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/validate-content-delivery-request.json", + "title": "Validate Content Delivery Request", + "description": "Request parameters for batch validating delivery records against content safety policies", + "type": "object", + "properties": { + "standards_id": { + "type": "string", + "description": "Standards configuration to validate against" + }, + "records": { + "type": "array", + "description": "Delivery records to validate (max 10,000)", + "minItems": 1, + "maxItems": 10000, + "items": { + "type": "object", + "properties": { + "record_id": { + "type": "string", + "description": "Unique identifier for this delivery record" + }, + "media_buy_id": { + "type": "string", + "description": "Media buy this record belongs to (when batching across multiple buys)" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "When the delivery occurred" + }, + "artifact": { + "title": "Artifact", + "description": "Artifact where ad was delivered", + "type": "object", + "properties": { + "property_id": { + "title": "Identifier", + "description": "Identifier for the property where this artifact appears", + "type": "object", + "properties": { + "type": { + "title": "Property Identifier Types", + "description": "Type of identifier", + "type": "string", + "enum": [ + "domain", + "subdomain", + "network_id", + "ios_bundle", + "android_package", + "apple_app_store_id", + "google_play_id", + "roku_store_id", + "fire_tv_asin", + "samsung_app_id", + "apple_tv_bundle", + "bundle_id", + "venue_id", + "screen_id", + "openooh_venue_type", + "rss_url", + "apple_podcast_id", + "spotify_show_id", + "podcast_guid" + ], + "examples": [ + "domain", + "ios_bundle", + "venue_id", + "apple_podcast_id" + ] + }, + "value": { + "type": "string", + "description": "The identifier value. For domain type: 'example.com' matches base domain plus www and m subdomains; 'edition.example.com' matches that specific subdomain; '*.example.com' matches ALL subdomains but NOT base domain" + } + }, + "required": [ + "type", + "value" + ], + "additionalProperties": false + }, + "artifact_id": { + "type": "string", + "description": "Identifier for this artifact within the property. The property owner defines the scheme (e.g., 'article_12345', 'episode_42_segment_3', 'post_abc123')." + }, + "variant_id": { + "type": "string", + "description": "Identifies a specific variant of this artifact. Use for A/B tests, translations, or temporal versions. Examples: 'en', 'es-MX', 'v2', 'headline_test_b'. The combination of artifact_id + variant_id must be unique." + }, + "format_id": { + "title": "Format ID", + "description": "Optional reference to a format definition. Uses the same format registry as creative formats.", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "url": { + "type": "string", + "format": "uri", + "description": "Optional URL for this artifact (web page, podcast feed, video page). Not all artifacts have URLs (e.g., Instagram content, podcast segments, TV scenes)." + }, + "published_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was published (ISO 8601 format)" + }, + "last_update_time": { + "type": "string", + "format": "date-time", + "description": "When the artifact was last modified (ISO 8601 format)" + }, + "assets": { + "type": "array", + "description": "Artifact assets in document flow order - text blocks, images, video, audio", + "items": { + "oneOf": [ + { + "type": "object", + "description": "Text block (paragraph, heading, etc.)", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "role": { + "type": "string", + "enum": [ + "title", + "paragraph", + "heading", + "caption", + "quote", + "list_item", + "description" + ], + "description": "Role of this text in the document. Use 'title' for the main artifact title, 'description' for summaries." + }, + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "BCP 47 language tag for this text (e.g., 'en', 'es-MX'). Useful when artifact contains mixed-language content." + }, + "heading_level": { + "type": "integer", + "minimum": 1, + "maximum": 6, + "description": "Heading level (1-6), only for role=heading" + } + }, + "required": [ + "type", + "content" + ] + }, + { + "type": "object", + "description": "Image asset", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Image URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "alt_text": { + "type": "string", + "description": "Alt text or image description" + }, + "caption": { + "type": "string", + "description": "Image caption" + }, + "width": { + "type": "integer", + "description": "Image width in pixels" + }, + "height": { + "type": "integer", + "description": "Image height in pixels" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Video asset", + "properties": { + "type": { + "type": "string", + "const": "video" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Video URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Video duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Video transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "subtitles", + "closed_captions", + "dub", + "generated" + ], + "description": "How the transcript was generated" + }, + "thumbnail_url": { + "type": "string", + "format": "uri", + "description": "Video thumbnail URL" + } + }, + "required": [ + "type", + "url" + ] + }, + { + "type": "object", + "description": "Audio asset", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Audio URL" + }, + "access": { + "$ref": "#/$defs/asset_access", + "description": "Authentication for secured URLs" + }, + "duration_ms": { + "type": "integer", + "description": "Audio duration in milliseconds" + }, + "transcript": { + "type": "string", + "description": "Audio transcript" + }, + "transcript_source": { + "type": "string", + "enum": [ + "original_script", + "closed_captions", + "generated" + ], + "description": "How the transcript was generated" + } + }, + "required": [ + "type", + "url" + ] + } + ] + } + }, + "metadata": { + "type": "object", + "description": "Rich metadata extracted from the artifact", + "properties": { + "canonical": { + "type": "string", + "format": "uri", + "description": "Canonical URL" + }, + "author": { + "type": "string", + "description": "Artifact author name" + }, + "keywords": { + "type": "string", + "description": "Artifact keywords" + }, + "open_graph": { + "type": "object", + "description": "Open Graph protocol metadata", + "additionalProperties": true + }, + "twitter_card": { + "type": "object", + "description": "Twitter Card metadata", + "additionalProperties": true + }, + "json_ld": { + "type": "array", + "description": "JSON-LD structured data (schema.org)", + "items": { + "type": "object" + } + } + }, + "additionalProperties": true + }, + "identifiers": { + "type": "object", + "description": "Platform-specific identifiers for this artifact", + "properties": { + "apple_podcast_id": { + "type": "string", + "description": "Apple Podcasts ID" + }, + "spotify_show_id": { + "type": "string", + "description": "Spotify show ID" + }, + "podcast_guid": { + "type": "string", + "description": "Podcast GUID (from RSS feed)" + }, + "youtube_video_id": { + "type": "string", + "description": "YouTube video ID" + }, + "rss_url": { + "type": "string", + "format": "uri", + "description": "RSS feed URL" + } + }, + "additionalProperties": true + } + }, + "required": [ + "property_id", + "artifact_id", + "assets" + ], + "additionalProperties": true, + "$defs": { + "asset_access": { + "type": "object", + "description": "Authentication for accessing secured asset URLs", + "oneOf": [ + { + "type": "object", + "description": "Bearer token authentication", + "properties": { + "method": { + "type": "string", + "const": "bearer_token" + }, + "token": { + "type": "string", + "description": "OAuth2 bearer token for Authorization header" + } + }, + "required": [ + "method", + "token" + ] + }, + { + "type": "object", + "description": "Service account authentication (GCP, AWS)", + "properties": { + "method": { + "type": "string", + "const": "service_account" + }, + "provider": { + "type": "string", + "enum": [ + "gcp", + "aws" + ], + "description": "Cloud provider" + }, + "credentials": { + "type": "object", + "description": "Service account credentials", + "additionalProperties": true + } + }, + "required": [ + "method", + "provider" + ] + }, + { + "type": "object", + "description": "Pre-signed URL (credentials embedded in URL)", + "properties": { + "method": { + "type": "string", + "const": "signed_url" + } + }, + "required": [ + "method" + ] + } + ] + } + } + }, + "country": { + "type": "string", + "description": "ISO 3166-1 alpha-2 country code where delivery occurred" + }, + "channel": { + "type": "string", + "description": "Channel type (e.g., display, video, audio, social)" + }, + "brand_context": { + "type": "object", + "description": "Brand information for policy evaluation. Schema TBD - placeholder for brand identifiers.", + "properties": { + "brand_id": { + "type": "string", + "description": "Brand identifier" + }, + "sku_id": { + "type": "string", + "description": "Product/SKU identifier if applicable" + } + } + } + }, + "required": [ + "record_id", + "artifact" + ] + } + }, + "feature_ids": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "Specific features to evaluate (defaults to all)" + }, + "include_passed": { + "type": "boolean", + "default": true, + "description": "Include passed records in results" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "standards_id", + "records" + ], + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.783Z", + "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/dist/schemas/3.0.0-beta.4/bundled/content-standards/validate-content-delivery-response.json b/dist/schemas/3.0.0-beta.4/bundled/content-standards/validate-content-delivery-response.json new file mode 100644 index 000000000..d55e603b0 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/content-standards/validate-content-delivery-response.json @@ -0,0 +1,183 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/content-standards/validate-content-delivery-response.json", + "title": "Validate Content Delivery Response", + "description": "Response payload with per-record verdicts and optional feature breakdown", + "type": "object", + "oneOf": [ + { + "type": "object", + "description": "Success response", + "properties": { + "summary": { + "type": "object", + "description": "Summary counts across all records", + "properties": { + "total_records": { + "type": "integer" + }, + "passed_records": { + "type": "integer" + }, + "failed_records": { + "type": "integer" + } + }, + "required": [ + "total_records", + "passed_records", + "failed_records" + ] + }, + "results": { + "type": "array", + "description": "Per-record evaluation results", + "items": { + "type": "object", + "properties": { + "record_id": { + "type": "string", + "description": "Which delivery record was evaluated" + }, + "verdict": { + "type": "string", + "enum": [ + "pass", + "fail" + ], + "description": "Overall pass/fail verdict for this record" + }, + "features": { + "type": "array", + "description": "Optional feature-level breakdown", + "items": { + "type": "object", + "properties": { + "feature_id": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "passed", + "failed", + "warning", + "unevaluated" + ] + }, + "value": {}, + "message": { + "type": "string" + }, + "rule_id": { + "type": "string", + "description": "Which rule triggered this result (e.g., GARM category, Scope3 standard)" + } + }, + "required": [ + "feature_id", + "status" + ] + } + } + }, + "required": [ + "record_id", + "verdict" + ] + } + }, + "errors": { + "not": {}, + "description": "Field must not be present in success response" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "summary", + "results" + ] + }, + { + "type": "object", + "description": "Error response", + "properties": { + "errors": { + "type": "array", + "items": { + "title": "Error", + "description": "Standard error structure for task-specific errors and warnings", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Error code for programmatic handling" + }, + "message": { + "type": "string", + "description": "Human-readable error message" + }, + "field": { + "type": "string", + "description": "Field path associated with the error (e.g., 'packages[0].targeting')" + }, + "suggestion": { + "type": "string", + "description": "Suggested fix for the error" + }, + "retry_after": { + "type": "number", + "description": "Seconds to wait before retrying the operation", + "minimum": 0 + }, + "details": { + "type": "object", + "description": "Additional task-specific error details", + "additionalProperties": true + } + }, + "required": [ + "code", + "message" + ], + "additionalProperties": true + } + }, + "summary": { + "not": {}, + "description": "Field must not be present in error response" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "errors" + ] + } + ], + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.784Z", + "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/dist/schemas/3.0.0-beta.4/bundled/core/tasks-get-request.json b/dist/schemas/3.0.0-beta.4/bundled/core/tasks-get-request.json new file mode 100644 index 000000000..44444bab1 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/core/tasks-get-request.json @@ -0,0 +1,53 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/core/tasks-get-request.json", + "title": "Tasks Get Request", + "description": "Request parameters for retrieving a specific task by ID with optional conversation history across all AdCP domains", + "type": "object", + "properties": { + "task_id": { + "type": "string", + "description": "Unique identifier of the task to retrieve" + }, + "include_history": { + "type": "boolean", + "default": false, + "description": "Include full conversation history for this task (may increase response size)" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "task_id" + ], + "additionalProperties": true, + "examples": [ + { + "description": "Check task status", + "data": { + "task_id": "task_456" + } + }, + { + "description": "Get task with full conversation history", + "data": { + "task_id": "task_123", + "include_history": true + } + } + ], + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.785Z", + "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/dist/schemas/3.0.0-beta.4/bundled/core/tasks-get-response.json b/dist/schemas/3.0.0-beta.4/bundled/core/tasks-get-response.json new file mode 100644 index 000000000..aafb6697c --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/core/tasks-get-response.json @@ -0,0 +1,244 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/core/tasks-get-response.json", + "title": "Tasks Get Response", + "description": "Response containing detailed information about a specific task including status and optional conversation history across all AdCP domains", + "type": "object", + "properties": { + "task_id": { + "type": "string", + "description": "Unique identifier for this task" + }, + "task_type": { + "title": "Task Type", + "description": "Type of AdCP operation", + "type": "string", + "enum": [ + "create_media_buy", + "update_media_buy", + "sync_creatives", + "activate_signal", + "get_signals", + "create_property_list", + "update_property_list", + "get_property_list", + "list_property_lists", + "delete_property_list", + "sync_accounts", + "get_account_financials", + "get_creative_delivery", + "sync_event_sources", + "sync_audiences", + "sync_catalogs", + "log_event" + ], + "enumDescriptions": { + "create_media_buy": "Media-buy domain: Create a new advertising campaign with one or more packages", + "update_media_buy": "Media-buy domain: Update campaign settings, package configuration, or delivery parameters", + "sync_creatives": "Media-buy domain: Sync creative assets to publisher's library with upsert semantics", + "activate_signal": "Signals domain: Activate an audience signal on a specific platform or account", + "get_signals": "Signals domain: Discover available audience signals based on natural language description", + "create_property_list": "Property domain: Create a new property list with filters and brand reference", + "update_property_list": "Property domain: Update an existing property list", + "get_property_list": "Property domain: Retrieve a property list with resolved properties", + "list_property_lists": "Property domain: List all accessible property lists", + "delete_property_list": "Property domain: Delete a property list", + "sync_accounts": "Account domain: Sync advertiser accounts with a seller using upsert semantics", + "get_account_financials": "Account domain: Query financial status of an operator-billed account (spend, credit, invoices)", + "get_creative_delivery": "Creative domain: Retrieve variant-level creative delivery data", + "sync_event_sources": "Media-buy domain: Configure event sources on an account with upsert semantics", + "sync_audiences": "Media-buy domain: Manage first-party CRM audiences on an account with delta upsert semantics", + "sync_catalogs": "Media-buy domain: Sync catalog feeds (products, inventory, stores, promotions, offerings) to a platform with approval workflow", + "log_event": "Media-buy domain: Send conversion or marketing events for attribution" + }, + "notes": [ + "Task types map to specific AdCP task operations", + "Each task type belongs to the 'media-buy', 'signals', 'property', 'account', or 'creative' domain", + "This enum is used in task management APIs (tasks/list, tasks/get) and webhook payloads", + "New task types require a minor version bump per semantic versioning" + ] + }, + "domain": { + "type": "string", + "description": "AdCP domain this task belongs to", + "enum": [ + "media-buy", + "signals" + ] + }, + "status": { + "title": "Task Status", + "description": "Current task status", + "type": "string", + "enum": [ + "submitted", + "working", + "input-required", + "completed", + "canceled", + "failed", + "rejected", + "auth-required", + "unknown" + ], + "enumDescriptions": { + "submitted": "Task accepted and queued for long-running execution (hours to days). Client should poll with tasks/get or provide webhook_url at protocol level.", + "working": "Agent is actively processing the task, expect completion within 120 seconds", + "input-required": "Task is paused and waiting for input from the user (e.g., clarification, approval)", + "completed": "Task has been successfully completed", + "canceled": "Task was canceled by the user", + "failed": "Task failed due to an error during execution", + "rejected": "Task was rejected by the agent and was not started", + "auth-required": "Task requires authentication to proceed", + "unknown": "Task is in an unknown or indeterminate state" + } + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "When the task was initially created (ISO 8601)" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "When the task was last updated (ISO 8601)" + }, + "completed_at": { + "type": "string", + "format": "date-time", + "description": "When the task completed (ISO 8601, only for completed/failed/canceled tasks)" + }, + "has_webhook": { + "type": "boolean", + "description": "Whether this task has webhook configuration" + }, + "progress": { + "type": "object", + "description": "Progress information for long-running tasks", + "properties": { + "percentage": { + "type": "number", + "minimum": 0, + "maximum": 100, + "description": "Completion percentage (0-100)" + }, + "current_step": { + "type": "string", + "description": "Current step or phase of the operation" + }, + "total_steps": { + "type": "integer", + "minimum": 1, + "description": "Total number of steps in the operation" + }, + "step_number": { + "type": "integer", + "minimum": 1, + "description": "Current step number" + } + }, + "additionalProperties": true + }, + "error": { + "type": "object", + "description": "Error details for failed tasks", + "properties": { + "code": { + "type": "string", + "description": "Error code for programmatic handling" + }, + "message": { + "type": "string", + "description": "Detailed error message" + }, + "details": { + "type": "object", + "description": "Additional error context", + "properties": { + "domain": { + "type": "string", + "description": "AdCP domain where error occurred", + "enum": [ + "media-buy", + "signals" + ] + }, + "operation": { + "type": "string", + "description": "Specific operation that failed" + }, + "specific_context": { + "type": "object", + "description": "Domain-specific error context", + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "required": [ + "code", + "message" + ], + "additionalProperties": true + }, + "history": { + "type": "array", + "description": "Complete conversation history for this task (only included if include_history was true in request)", + "items": { + "type": "object", + "properties": { + "timestamp": { + "type": "string", + "format": "date-time", + "description": "When this exchange occurred (ISO 8601)" + }, + "type": { + "type": "string", + "enum": [ + "request", + "response" + ], + "description": "Whether this was a request from client or response from server" + }, + "data": { + "type": "object", + "description": "The full request or response payload", + "additionalProperties": true + } + }, + "required": [ + "timestamp", + "type", + "data" + ], + "additionalProperties": true + } + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "task_id", + "task_type", + "domain", + "status", + "created_at", + "updated_at" + ], + "additionalProperties": true, + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.786Z", + "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/dist/schemas/3.0.0-beta.4/bundled/core/tasks-list-request.json b/dist/schemas/3.0.0-beta.4/bundled/core/tasks-list-request.json new file mode 100644 index 000000000..9d37c2723 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/core/tasks-list-request.json @@ -0,0 +1,375 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/core/tasks-list-request.json", + "title": "Tasks List Request", + "description": "Request parameters for listing and filtering async tasks across all AdCP domains with state reconciliation capabilities", + "type": "object", + "properties": { + "filters": { + "type": "object", + "description": "Filter criteria for querying tasks", + "properties": { + "domain": { + "title": "AdCP Domain", + "description": "Filter by single AdCP domain", + "type": "string", + "enum": [ + "media-buy", + "signals", + "governance", + "creative" + ], + "enumDescriptions": { + "media-buy": "Campaign creation, package management, delivery optimization, and conversion tracking", + "signals": "Audience signal discovery and activation", + "governance": "Property governance (identity, authorization, data, selection), brand standards, and compliance", + "creative": "Creative asset management, format discovery, and rendering" + } + }, + "domains": { + "type": "array", + "description": "Filter by multiple AdCP domains", + "items": { + "title": "AdCP Domain", + "description": "AdCP protocol domains for task categorization", + "type": "string", + "enum": [ + "media-buy", + "signals", + "governance", + "creative" + ], + "enumDescriptions": { + "media-buy": "Campaign creation, package management, delivery optimization, and conversion tracking", + "signals": "Audience signal discovery and activation", + "governance": "Property governance (identity, authorization, data, selection), brand standards, and compliance", + "creative": "Creative asset management, format discovery, and rendering" + } + }, + "minItems": 1 + }, + "status": { + "title": "Task Status", + "description": "Filter by single task status", + "type": "string", + "enum": [ + "submitted", + "working", + "input-required", + "completed", + "canceled", + "failed", + "rejected", + "auth-required", + "unknown" + ], + "enumDescriptions": { + "submitted": "Task accepted and queued for long-running execution (hours to days). Client should poll with tasks/get or provide webhook_url at protocol level.", + "working": "Agent is actively processing the task, expect completion within 120 seconds", + "input-required": "Task is paused and waiting for input from the user (e.g., clarification, approval)", + "completed": "Task has been successfully completed", + "canceled": "Task was canceled by the user", + "failed": "Task failed due to an error during execution", + "rejected": "Task was rejected by the agent and was not started", + "auth-required": "Task requires authentication to proceed", + "unknown": "Task is in an unknown or indeterminate state" + } + }, + "statuses": { + "type": "array", + "description": "Filter by multiple task statuses", + "items": { + "title": "Task Status", + "description": "Standardized task status values based on A2A TaskState enum. Indicates the current state of any AdCP operation.", + "type": "string", + "enum": [ + "submitted", + "working", + "input-required", + "completed", + "canceled", + "failed", + "rejected", + "auth-required", + "unknown" + ], + "enumDescriptions": { + "submitted": "Task accepted and queued for long-running execution (hours to days). Client should poll with tasks/get or provide webhook_url at protocol level.", + "working": "Agent is actively processing the task, expect completion within 120 seconds", + "input-required": "Task is paused and waiting for input from the user (e.g., clarification, approval)", + "completed": "Task has been successfully completed", + "canceled": "Task was canceled by the user", + "failed": "Task failed due to an error during execution", + "rejected": "Task was rejected by the agent and was not started", + "auth-required": "Task requires authentication to proceed", + "unknown": "Task is in an unknown or indeterminate state" + } + }, + "minItems": 1 + }, + "task_type": { + "title": "Task Type", + "description": "Filter by single task type", + "type": "string", + "enum": [ + "create_media_buy", + "update_media_buy", + "sync_creatives", + "activate_signal", + "get_signals", + "create_property_list", + "update_property_list", + "get_property_list", + "list_property_lists", + "delete_property_list", + "sync_accounts", + "get_account_financials", + "get_creative_delivery", + "sync_event_sources", + "sync_audiences", + "sync_catalogs", + "log_event" + ], + "enumDescriptions": { + "create_media_buy": "Media-buy domain: Create a new advertising campaign with one or more packages", + "update_media_buy": "Media-buy domain: Update campaign settings, package configuration, or delivery parameters", + "sync_creatives": "Media-buy domain: Sync creative assets to publisher's library with upsert semantics", + "activate_signal": "Signals domain: Activate an audience signal on a specific platform or account", + "get_signals": "Signals domain: Discover available audience signals based on natural language description", + "create_property_list": "Property domain: Create a new property list with filters and brand reference", + "update_property_list": "Property domain: Update an existing property list", + "get_property_list": "Property domain: Retrieve a property list with resolved properties", + "list_property_lists": "Property domain: List all accessible property lists", + "delete_property_list": "Property domain: Delete a property list", + "sync_accounts": "Account domain: Sync advertiser accounts with a seller using upsert semantics", + "get_account_financials": "Account domain: Query financial status of an operator-billed account (spend, credit, invoices)", + "get_creative_delivery": "Creative domain: Retrieve variant-level creative delivery data", + "sync_event_sources": "Media-buy domain: Configure event sources on an account with upsert semantics", + "sync_audiences": "Media-buy domain: Manage first-party CRM audiences on an account with delta upsert semantics", + "sync_catalogs": "Media-buy domain: Sync catalog feeds (products, inventory, stores, promotions, offerings) to a platform with approval workflow", + "log_event": "Media-buy domain: Send conversion or marketing events for attribution" + }, + "notes": [ + "Task types map to specific AdCP task operations", + "Each task type belongs to the 'media-buy', 'signals', 'property', 'account', or 'creative' domain", + "This enum is used in task management APIs (tasks/list, tasks/get) and webhook payloads", + "New task types require a minor version bump per semantic versioning" + ] + }, + "task_types": { + "type": "array", + "description": "Filter by multiple task types", + "items": { + "title": "Task Type", + "description": "Valid AdCP task types across all domains. These represent the complete set of operations that can be tracked via the task management system.", + "type": "string", + "enum": [ + "create_media_buy", + "update_media_buy", + "sync_creatives", + "activate_signal", + "get_signals", + "create_property_list", + "update_property_list", + "get_property_list", + "list_property_lists", + "delete_property_list", + "sync_accounts", + "get_account_financials", + "get_creative_delivery", + "sync_event_sources", + "sync_audiences", + "sync_catalogs", + "log_event" + ], + "enumDescriptions": { + "create_media_buy": "Media-buy domain: Create a new advertising campaign with one or more packages", + "update_media_buy": "Media-buy domain: Update campaign settings, package configuration, or delivery parameters", + "sync_creatives": "Media-buy domain: Sync creative assets to publisher's library with upsert semantics", + "activate_signal": "Signals domain: Activate an audience signal on a specific platform or account", + "get_signals": "Signals domain: Discover available audience signals based on natural language description", + "create_property_list": "Property domain: Create a new property list with filters and brand reference", + "update_property_list": "Property domain: Update an existing property list", + "get_property_list": "Property domain: Retrieve a property list with resolved properties", + "list_property_lists": "Property domain: List all accessible property lists", + "delete_property_list": "Property domain: Delete a property list", + "sync_accounts": "Account domain: Sync advertiser accounts with a seller using upsert semantics", + "get_account_financials": "Account domain: Query financial status of an operator-billed account (spend, credit, invoices)", + "get_creative_delivery": "Creative domain: Retrieve variant-level creative delivery data", + "sync_event_sources": "Media-buy domain: Configure event sources on an account with upsert semantics", + "sync_audiences": "Media-buy domain: Manage first-party CRM audiences on an account with delta upsert semantics", + "sync_catalogs": "Media-buy domain: Sync catalog feeds (products, inventory, stores, promotions, offerings) to a platform with approval workflow", + "log_event": "Media-buy domain: Send conversion or marketing events for attribution" + }, + "notes": [ + "Task types map to specific AdCP task operations", + "Each task type belongs to the 'media-buy', 'signals', 'property', 'account', or 'creative' domain", + "This enum is used in task management APIs (tasks/list, tasks/get) and webhook payloads", + "New task types require a minor version bump per semantic versioning" + ] + }, + "minItems": 1 + }, + "created_after": { + "type": "string", + "format": "date-time", + "description": "Filter tasks created after this date (ISO 8601)" + }, + "created_before": { + "type": "string", + "format": "date-time", + "description": "Filter tasks created before this date (ISO 8601)" + }, + "updated_after": { + "type": "string", + "format": "date-time", + "description": "Filter tasks last updated after this date (ISO 8601)" + }, + "updated_before": { + "type": "string", + "format": "date-time", + "description": "Filter tasks last updated before this date (ISO 8601)" + }, + "task_ids": { + "type": "array", + "description": "Filter by specific task IDs", + "items": { + "type": "string" + }, + "minItems": 1, + "maxItems": 100 + }, + "context_contains": { + "type": "string", + "description": "Filter tasks where context contains this text (searches buyer_ref, media_buy_id, signal_id, etc.)" + }, + "has_webhook": { + "type": "boolean", + "description": "Filter tasks that have webhook configuration when true" + } + }, + "additionalProperties": true + }, + "sort": { + "type": "object", + "description": "Sorting parameters", + "properties": { + "field": { + "type": "string", + "enum": [ + "created_at", + "updated_at", + "status", + "task_type", + "domain" + ], + "default": "created_at", + "description": "Field to sort by" + }, + "direction": { + "title": "Sort Direction", + "description": "Sort direction", + "type": "string", + "enum": [ + "asc", + "desc" + ], + "default": "desc" + } + }, + "additionalProperties": true + }, + "pagination": { + "title": "Pagination Request", + "description": "Standard cursor-based pagination parameters for list operations", + "type": "object", + "properties": { + "max_results": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 50, + "description": "Maximum number of items to return per page" + }, + "cursor": { + "type": "string", + "description": "Opaque cursor from a previous response to fetch the next page" + } + }, + "additionalProperties": false + }, + "include_history": { + "type": "boolean", + "default": false, + "description": "Include full conversation history for each task (may significantly increase response size)" + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": true, + "examples": [ + { + "description": "List all pending tasks across domains", + "data": { + "filters": { + "statuses": [ + "submitted", + "working", + "input-required" + ] + } + } + }, + { + "description": "Find media-buy tasks requiring attention", + "data": { + "filters": { + "domain": "media-buy", + "statuses": [ + "input-required", + "failed" + ] + }, + "sort": { + "field": "updated_at", + "direction": "asc" + } + } + }, + { + "description": "Recent signal operations", + "data": { + "filters": { + "domain": "signals", + "created_after": "2025-01-01T00:00:00Z" + }, + "pagination": { + "max_results": 20 + } + } + }, + { + "description": "State reconciliation for specific campaign", + "data": { + "filters": { + "context_contains": "nike_q1_2025" + }, + "include_history": true + } + } + ], + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.786Z", + "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/dist/schemas/3.0.0-beta.4/bundled/core/tasks-list-response.json b/dist/schemas/3.0.0-beta.4/bundled/core/tasks-list-response.json new file mode 100644 index 000000000..8e32f8ac5 --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/core/tasks-list-response.json @@ -0,0 +1,251 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/core/tasks-list-response.json", + "title": "Tasks List Response", + "description": "Response from task listing query with filtered results and state reconciliation data across all AdCP domains", + "type": "object", + "properties": { + "query_summary": { + "type": "object", + "description": "Summary of the query that was executed", + "properties": { + "total_matching": { + "type": "integer", + "description": "Total number of tasks matching filters (across all pages)", + "minimum": 0 + }, + "returned": { + "type": "integer", + "description": "Number of tasks returned in this response", + "minimum": 0 + }, + "domain_breakdown": { + "type": "object", + "description": "Count of tasks by domain", + "properties": { + "media-buy": { + "type": "integer", + "minimum": 0, + "description": "Number of media-buy tasks in results" + }, + "signals": { + "type": "integer", + "minimum": 0, + "description": "Number of signals tasks in results" + } + }, + "additionalProperties": true + }, + "status_breakdown": { + "type": "object", + "description": "Count of tasks by status", + "additionalProperties": { + "type": "integer", + "minimum": 0 + } + }, + "filters_applied": { + "type": "array", + "description": "List of filters that were applied to the query", + "items": { + "type": "string" + } + }, + "sort_applied": { + "type": "object", + "description": "Sort order that was applied", + "properties": { + "field": { + "type": "string" + }, + "direction": { + "type": "string", + "enum": [ + "asc", + "desc" + ] + } + }, + "required": [ + "field", + "direction" + ], + "additionalProperties": true + } + }, + "required": [], + "additionalProperties": true + }, + "tasks": { + "type": "array", + "description": "Array of tasks matching the query criteria", + "items": { + "type": "object", + "properties": { + "task_id": { + "type": "string", + "description": "Unique identifier for this task" + }, + "task_type": { + "title": "Task Type", + "description": "Type of AdCP operation", + "type": "string", + "enum": [ + "create_media_buy", + "update_media_buy", + "sync_creatives", + "activate_signal", + "get_signals", + "create_property_list", + "update_property_list", + "get_property_list", + "list_property_lists", + "delete_property_list", + "sync_accounts", + "get_account_financials", + "get_creative_delivery", + "sync_event_sources", + "sync_audiences", + "sync_catalogs", + "log_event" + ], + "enumDescriptions": { + "create_media_buy": "Media-buy domain: Create a new advertising campaign with one or more packages", + "update_media_buy": "Media-buy domain: Update campaign settings, package configuration, or delivery parameters", + "sync_creatives": "Media-buy domain: Sync creative assets to publisher's library with upsert semantics", + "activate_signal": "Signals domain: Activate an audience signal on a specific platform or account", + "get_signals": "Signals domain: Discover available audience signals based on natural language description", + "create_property_list": "Property domain: Create a new property list with filters and brand reference", + "update_property_list": "Property domain: Update an existing property list", + "get_property_list": "Property domain: Retrieve a property list with resolved properties", + "list_property_lists": "Property domain: List all accessible property lists", + "delete_property_list": "Property domain: Delete a property list", + "sync_accounts": "Account domain: Sync advertiser accounts with a seller using upsert semantics", + "get_account_financials": "Account domain: Query financial status of an operator-billed account (spend, credit, invoices)", + "get_creative_delivery": "Creative domain: Retrieve variant-level creative delivery data", + "sync_event_sources": "Media-buy domain: Configure event sources on an account with upsert semantics", + "sync_audiences": "Media-buy domain: Manage first-party CRM audiences on an account with delta upsert semantics", + "sync_catalogs": "Media-buy domain: Sync catalog feeds (products, inventory, stores, promotions, offerings) to a platform with approval workflow", + "log_event": "Media-buy domain: Send conversion or marketing events for attribution" + }, + "notes": [ + "Task types map to specific AdCP task operations", + "Each task type belongs to the 'media-buy', 'signals', 'property', 'account', or 'creative' domain", + "This enum is used in task management APIs (tasks/list, tasks/get) and webhook payloads", + "New task types require a minor version bump per semantic versioning" + ] + }, + "domain": { + "type": "string", + "description": "AdCP domain this task belongs to", + "enum": [ + "media-buy", + "signals" + ] + }, + "status": { + "title": "Task Status", + "description": "Current task status", + "type": "string", + "enum": [ + "submitted", + "working", + "input-required", + "completed", + "canceled", + "failed", + "rejected", + "auth-required", + "unknown" + ], + "enumDescriptions": { + "submitted": "Task accepted and queued for long-running execution (hours to days). Client should poll with tasks/get or provide webhook_url at protocol level.", + "working": "Agent is actively processing the task, expect completion within 120 seconds", + "input-required": "Task is paused and waiting for input from the user (e.g., clarification, approval)", + "completed": "Task has been successfully completed", + "canceled": "Task was canceled by the user", + "failed": "Task failed due to an error during execution", + "rejected": "Task was rejected by the agent and was not started", + "auth-required": "Task requires authentication to proceed", + "unknown": "Task is in an unknown or indeterminate state" + } + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "When the task was initially created (ISO 8601)" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "When the task was last updated (ISO 8601)" + }, + "completed_at": { + "type": "string", + "format": "date-time", + "description": "When the task completed (ISO 8601, only for completed/failed/canceled tasks)" + }, + "has_webhook": { + "type": "boolean", + "description": "Whether this task has webhook configuration" + } + }, + "required": [ + "task_id", + "task_type", + "domain", + "status", + "created_at", + "updated_at" + ], + "additionalProperties": true + } + }, + "pagination": { + "title": "Pagination Response", + "description": "Standard cursor-based pagination metadata for list responses", + "type": "object", + "properties": { + "has_more": { + "type": "boolean", + "description": "Whether more results are available beyond this page" + }, + "cursor": { + "type": "string", + "description": "Opaque cursor to pass in the next request to fetch the next page. Only present when has_more is true." + }, + "total_count": { + "type": "integer", + "minimum": 0, + "description": "Total number of items matching the query across all pages. Optional because not all backends can efficiently compute this." + } + }, + "required": [ + "has_more" + ], + "additionalProperties": false + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "query_summary", + "tasks", + "pagination" + ], + "additionalProperties": true, + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.787Z", + "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/dist/schemas/3.0.0-beta.4/bundled/creative/get-creative-delivery-request.json b/dist/schemas/3.0.0-beta.4/bundled/creative/get-creative-delivery-request.json new file mode 100644 index 000000000..685ce449a --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/creative/get-creative-delivery-request.json @@ -0,0 +1,195 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/creative/get-creative-delivery-request.json", + "title": "Get Creative Delivery Request", + "description": "Request parameters for retrieving creative delivery data including variant-level metrics from a creative agent. At least one scoping filter (media_buy_ids, media_buy_buyer_refs, or creative_ids) is required.", + "type": "object", + "properties": { + "account": { + "title": "Account Reference", + "description": "Account for routing and scoping. Limits results to creatives within this account.", + "type": "object", + "oneOf": [ + { + "properties": { + "account_id": { + "type": "string", + "description": "Seller-assigned account identifier (from sync_accounts or list_accounts)" + } + }, + "required": [ + "account_id" + ], + "additionalProperties": false + }, + { + "properties": { + "brand": { + "title": "Brand Reference", + "description": "Brand reference identifying the advertiser", + "type": "object", + "properties": { + "domain": { + "type": "string", + "description": "Domain where /.well-known/brand.json is hosted, or the brand's operating domain", + "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$" + }, + "brand_id": { + "title": "Brand ID", + "description": "Brand identifier within the house portfolio. Optional for single-brand domains.", + "type": "string", + "pattern": "^[a-z0-9_]+$", + "examples": [ + "tide", + "cheerios", + "air_jordan", + "nike", + "pampers" + ] + } + }, + "required": [ + "domain" + ], + "additionalProperties": false, + "examples": [ + { + "domain": "nova-brands.com", + "brand_id": "spark" + }, + { + "domain": "nova-brands.com", + "brand_id": "glow" + }, + { + "domain": "acme-corp.com" + } + ] + }, + "operator": { + "type": "string", + "description": "Domain of the entity operating on the brand's behalf. When the brand operates directly, this is the brand's domain.", + "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$" + } + }, + "required": [ + "brand", + "operator" + ], + "additionalProperties": false + } + ], + "examples": [ + { + "account_id": "acc_acme_001" + }, + { + "brand": { + "domain": "acme-corp.com" + }, + "operator": "acme-corp.com" + }, + { + "brand": { + "domain": "nova-brands.com", + "brand_id": "spark" + }, + "operator": "pinnacle-media.com" + } + ] + }, + "media_buy_ids": { + "type": "array", + "description": "Filter to specific media buys by publisher ID. If omitted, returns creative delivery across all matching media buys.", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "media_buy_buyer_refs": { + "type": "array", + "description": "Filter to specific media buys by buyer reference ID. Alternative to media_buy_ids when the buyer doesn't have the publisher's identifiers.", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "creative_ids": { + "type": "array", + "description": "Filter to specific creatives by ID. If omitted, returns delivery for all creatives matching the other filters.", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "start_date": { + "type": "string", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "description": "Start date for delivery period (YYYY-MM-DD). Interpreted in the platform's reporting timezone." + }, + "end_date": { + "type": "string", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "description": "End date for delivery period (YYYY-MM-DD). Interpreted in the platform's reporting timezone." + }, + "max_variants": { + "type": "integer", + "description": "Maximum number of variants to return per creative. When omitted, the agent returns all variants. Use this to limit response size for generative creatives that may produce large numbers of variants.", + "minimum": 1 + }, + "pagination": { + "type": "object", + "description": "Pagination parameters for the creatives array in the response. When omitted, the agent returns all matching creatives.", + "properties": { + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 50, + "description": "Maximum number of creatives to return" + }, + "offset": { + "type": "integer", + "minimum": 0, + "default": 0, + "description": "Number of creatives to skip" + } + }, + "additionalProperties": true + }, + "context": { + "title": "Context Object", + "description": "Opaque correlation data that is echoed unchanged in responses. Used for internal tracking, UI session IDs, trace IDs, and other caller-specific identifiers that don't affect protocol behavior. Context data is never parsed by AdCP agents - it's simply preserved and returned.", + "type": "object", + "additionalProperties": true + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "anyOf": [ + { + "required": [ + "media_buy_ids" + ] + }, + { + "required": [ + "media_buy_buyer_refs" + ] + }, + { + "required": [ + "creative_ids" + ] + } + ], + "additionalProperties": true, + "_bundled": { + "generatedAt": "2026-02-26T12:28:33.788Z", + "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." + } +} \ No newline at end of file diff --git a/dist/schemas/3.0.0-beta.4/bundled/creative/get-creative-delivery-response.json b/dist/schemas/3.0.0-beta.4/bundled/creative/get-creative-delivery-response.json new file mode 100644 index 000000000..7a76c4e3e --- /dev/null +++ b/dist/schemas/3.0.0-beta.4/bundled/creative/get-creative-delivery-response.json @@ -0,0 +1,2821 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/3.0.0-beta.4/bundled/creative/get-creative-delivery-response.json", + "title": "Get Creative Delivery Response", + "description": "Response payload for get_creative_delivery task. Returns creative delivery data with variant-level breakdowns including manifests and metrics.", + "type": "object", + "properties": { + "account_id": { + "type": "string", + "description": "Account identifier. Present when the response spans or is scoped to a specific account." + }, + "media_buy_id": { + "type": "string", + "description": "Publisher's media buy identifier. Present when the request was scoped to a single media buy." + }, + "media_buy_buyer_ref": { + "type": "string", + "description": "Buyer's reference identifier for the media buy. Echoed back so the buyer can correlate without mapping publisher IDs." + }, + "currency": { + "type": "string", + "description": "ISO 4217 currency code for monetary values in this response (e.g., 'USD', 'EUR')", + "pattern": "^[A-Z]{3}$" + }, + "reporting_period": { + "type": "object", + "description": "Date range for the report.", + "properties": { + "start": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 start timestamp" + }, + "end": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 end timestamp" + }, + "timezone": { + "type": "string", + "description": "IANA timezone identifier for the reporting period (e.g., 'America/New_York', 'UTC'). Platforms report in their native timezone." + } + }, + "required": [ + "start", + "end" + ], + "additionalProperties": true + }, + "creatives": { + "type": "array", + "description": "Creative delivery data with variant breakdowns", + "items": { + "type": "object", + "properties": { + "creative_id": { + "type": "string", + "description": "Creative identifier" + }, + "media_buy_id": { + "type": "string", + "description": "Publisher's media buy identifier for this creative. Present when the request spanned multiple media buys, so the buyer can correlate each creative to its media buy." + }, + "format_id": { + "title": "Format ID", + "description": "Format of this creative", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "totals": { + "title": "Delivery Metrics", + "description": "Aggregate delivery metrics across all variants of this creative", + "type": "object", + "properties": { + "impressions": { + "type": "number", + "description": "Impressions delivered", + "minimum": 0 + }, + "spend": { + "type": "number", + "description": "Amount spent", + "minimum": 0 + }, + "clicks": { + "type": "number", + "description": "Total clicks", + "minimum": 0 + }, + "ctr": { + "type": "number", + "description": "Click-through rate (clicks/impressions)", + "minimum": 0, + "maximum": 1 + }, + "views": { + "type": "number", + "description": "Views at threshold (for CPV)", + "minimum": 0 + }, + "completed_views": { + "type": "number", + "description": "Video/audio completions. When the package has a completed_views optimization goal with view_duration_seconds, completions are counted at that threshold rather than 100% completion.", + "minimum": 0 + }, + "completion_rate": { + "type": "number", + "description": "Completion rate (completed_views/impressions)", + "minimum": 0, + "maximum": 1 + }, + "conversions": { + "type": "number", + "description": "Total conversions attributed to this delivery. When by_event_type is present, this equals the sum of all by_event_type[].count entries.", + "minimum": 0 + }, + "conversion_value": { + "type": "number", + "description": "Total monetary value of attributed conversions (in the reporting currency)", + "minimum": 0 + }, + "roas": { + "type": "number", + "description": "Return on ad spend (conversion_value / spend)", + "minimum": 0 + }, + "cost_per_acquisition": { + "type": "number", + "description": "Cost per conversion (spend / conversions)", + "minimum": 0 + }, + "new_to_brand_rate": { + "type": "number", + "description": "Fraction of conversions from first-time brand buyers (0 = none, 1 = all)", + "minimum": 0, + "maximum": 1 + }, + "leads": { + "type": "number", + "description": "Leads generated (convenience alias for by_event_type where event_type='lead')", + "minimum": 0 + }, + "by_event_type": { + "type": "array", + "description": "Conversion metrics broken down by event type. Spend-derived metrics (ROAS, CPA) are only available at the package/totals level since spend cannot be attributed to individual event types.", + "items": { + "type": "object", + "properties": { + "event_type": { + "title": "Event Type", + "description": "The event type", + "type": "string", + "enum": [ + "page_view", + "view_content", + "select_content", + "select_item", + "search", + "share", + "add_to_cart", + "remove_from_cart", + "viewed_cart", + "add_to_wishlist", + "initiate_checkout", + "add_payment_info", + "purchase", + "refund", + "lead", + "qualify_lead", + "close_convert_lead", + "disqualify_lead", + "complete_registration", + "subscribe", + "start_trial", + "app_install", + "app_launch", + "contact", + "schedule", + "donate", + "submit_application", + "custom" + ], + "enumDescriptions": { + "page_view": "User viewed a page", + "view_content": "User viewed specific content (product, article, etc.)", + "select_content": "User selected or clicked on content (article, video, etc.)", + "select_item": "User selected a specific product or item from a list", + "search": "User performed a search", + "share": "User shared content via social or messaging", + "add_to_cart": "User added an item to cart", + "remove_from_cart": "User removed an item from cart", + "viewed_cart": "User viewed their shopping cart", + "add_to_wishlist": "User added an item to a wishlist", + "initiate_checkout": "User started checkout process", + "add_payment_info": "User added payment information", + "purchase": "User completed a purchase", + "refund": "A purchase was fully or partially refunded (adjusts ROAS)", + "lead": "User expressed interest (form submission, signup, etc.)", + "qualify_lead": "Lead qualified by sales or scoring criteria", + "close_convert_lead": "Lead converted to a customer or closed deal", + "disqualify_lead": "Lead disqualified or marked as not viable", + "complete_registration": "User completed account registration", + "subscribe": "User subscribed to a service or newsletter", + "start_trial": "User started a free trial", + "app_install": "User installed an application", + "app_launch": "User launched an application", + "contact": "User initiated contact (call, message, etc.)", + "schedule": "User scheduled an appointment or event", + "donate": "User made a donation", + "submit_application": "User submitted an application (loan, job, etc.)", + "custom": "Custom event type (specify in custom_event_name)" + } + }, + "event_source_id": { + "type": "string", + "description": "Event source that produced these conversions (for disambiguation when multiple event sources are configured)" + }, + "count": { + "type": "number", + "description": "Number of events of this type", + "minimum": 0 + }, + "value": { + "type": "number", + "description": "Total monetary value of events of this type", + "minimum": 0 + } + }, + "required": [ + "event_type", + "count" + ], + "additionalProperties": true + } + }, + "grps": { + "type": "number", + "description": "Gross Rating Points delivered (for CPP)", + "minimum": 0 + }, + "reach": { + "type": "number", + "description": "Unique reach - units depend on measurement provider (e.g., individuals, households, devices, cookies). See delivery_measurement.provider for methodology.", + "minimum": 0 + }, + "frequency": { + "type": "number", + "description": "Average frequency per individual (typically measured over campaign duration, but can vary by measurement provider)", + "minimum": 0 + }, + "quartile_data": { + "type": "object", + "description": "Video quartile completion data", + "properties": { + "q1_views": { + "type": "number", + "description": "25% completion views", + "minimum": 0 + }, + "q2_views": { + "type": "number", + "description": "50% completion views", + "minimum": 0 + }, + "q3_views": { + "type": "number", + "description": "75% completion views", + "minimum": 0 + }, + "q4_views": { + "type": "number", + "description": "100% completion views", + "minimum": 0 + } + } + }, + "dooh_metrics": { + "type": "object", + "description": "DOOH-specific metrics (only included for DOOH campaigns)", + "properties": { + "loop_plays": { + "type": "integer", + "description": "Number of times ad played in rotation", + "minimum": 0 + }, + "screens_used": { + "type": "integer", + "description": "Number of unique screens displaying the ad", + "minimum": 0 + }, + "screen_time_seconds": { + "type": "integer", + "description": "Total display time in seconds", + "minimum": 0 + }, + "sov_achieved": { + "type": "number", + "description": "Actual share of voice delivered (0.0 to 1.0)", + "minimum": 0, + "maximum": 1 + }, + "calculation_notes": { + "type": "string", + "description": "Explanation of how DOOH impressions were calculated" + }, + "venue_breakdown": { + "type": "array", + "description": "Per-venue performance breakdown", + "items": { + "type": "object", + "properties": { + "venue_id": { + "type": "string", + "description": "Venue identifier" + }, + "venue_name": { + "type": "string", + "description": "Human-readable venue name" + }, + "venue_type": { + "type": "string", + "description": "Venue type (e.g., 'airport', 'transit', 'retail', 'billboard')" + }, + "impressions": { + "type": "integer", + "description": "Impressions delivered at this venue", + "minimum": 0 + }, + "loop_plays": { + "type": "integer", + "description": "Loop plays at this venue", + "minimum": 0 + }, + "screens_used": { + "type": "integer", + "description": "Number of screens used at this venue", + "minimum": 0 + } + }, + "required": [ + "venue_id", + "impressions" + ], + "additionalProperties": true + } + } + }, + "additionalProperties": true + }, + "viewability": { + "type": "object", + "description": "Viewability metrics. Viewable rate should be calculated as viewable_impressions / measurable_impressions (not total impressions), since some environments cannot measure viewability.", + "properties": { + "measurable_impressions": { + "type": "number", + "description": "Impressions where viewability could be measured. Excludes environments without measurement capability (e.g., non-Intersection Observer browsers, certain app environments).", + "minimum": 0 + }, + "viewable_impressions": { + "type": "number", + "description": "Impressions that met the viewability threshold defined by the measurement standard.", + "minimum": 0 + }, + "viewable_rate": { + "type": "number", + "description": "Viewable impression rate (viewable_impressions / measurable_impressions). Range 0.0 to 1.0.", + "minimum": 0, + "maximum": 1 + }, + "standard": { + "type": "string", + "enum": [ + "mrc", + "groupm" + ], + "description": "Viewability measurement standard. 'mrc': 50% of pixels in view for 1 second (display) or 2 seconds (video), per MRC/IAB guidelines. 'groupm': 100% of pixels in view for the same durations. These are materially different thresholds and should not be compared across standards." + } + }, + "additionalProperties": true + }, + "engagements": { + "type": "number", + "description": "Total engagements — direct interactions with the ad beyond viewing. Includes social reactions/comments/shares, story/unit opens, interactive overlay taps on CTV, companion banner interactions on audio. Platform-specific; corresponds to the 'engagements' optimization metric.", + "minimum": 0 + }, + "follows": { + "type": "number", + "description": "New followers, page likes, artist/podcast/channel subscribes attributed to this delivery.", + "minimum": 0 + }, + "saves": { + "type": "number", + "description": "Saves, bookmarks, playlist adds, pins attributed to this delivery.", + "minimum": 0 + }, + "profile_visits": { + "type": "number", + "description": "Visits to the brand's in-platform page (profile, artist page, channel, or storefront) attributed to this delivery. Does not include external website clicks.", + "minimum": 0 + }, + "engagement_rate": { + "type": "number", + "description": "Platform-specific engagement rate (0.0 to 1.0). Typically engagements/impressions, but definition varies by platform.", + "minimum": 0, + "maximum": 1 + }, + "cost_per_click": { + "type": "number", + "description": "Cost per click (spend / clicks)", + "minimum": 0 + }, + "by_action_source": { + "type": "array", + "description": "Conversion metrics broken down by action source (website, app, in_store, etc.). Useful for omnichannel sellers where conversions occur across digital and physical channels.", + "items": { + "type": "object", + "properties": { + "action_source": { + "title": "Action Source", + "description": "Where the conversion occurred", + "type": "string", + "enum": [ + "website", + "app", + "offline", + "phone_call", + "chat", + "email", + "in_store", + "system_generated", + "other" + ], + "enumDescriptions": { + "website": "Event occurred on a website", + "app": "Event occurred in a mobile or desktop app", + "offline": "Event occurred offline (imported data)", + "phone_call": "Event originated from a phone call", + "chat": "Event originated from a chat conversation", + "email": "Event originated from an email interaction", + "in_store": "Event occurred at a physical retail location", + "system_generated": "Event generated by an automated system", + "other": "Other source (specify in ext)" + } + }, + "event_source_id": { + "type": "string", + "description": "Event source that produced these conversions (for disambiguation when multiple event sources are configured)" + }, + "count": { + "type": "number", + "description": "Number of conversions from this action source", + "minimum": 0 + }, + "value": { + "type": "number", + "description": "Total monetary value of conversions from this action source", + "minimum": 0 + } + }, + "required": [ + "action_source", + "count" + ], + "additionalProperties": true + } + } + }, + "additionalProperties": true + }, + "variant_count": { + "type": "integer", + "description": "Total number of variants for this creative. When max_variants was specified in the request, this may exceed the number of items in the variants array.", + "minimum": 0 + }, + "variants": { + "type": "array", + "description": "Variant-level delivery breakdown. Each variant includes the rendered manifest and delivery metrics. For standard creatives, contains a single variant. For asset group optimization, one per combination. For generative creative, one per generated execution. Empty when a creative has no variants yet.", + "items": { + "title": "Creative Variant", + "description": "A specific execution variant of a creative with delivery metrics. For catalog-driven packages, each catalog item rendered as a distinct ad execution is a variant — the variant's manifest includes the catalog reference with the specific item rendered. For asset group optimization, represents one combination of assets the platform selected. For generative creative, represents a platform-generated variant. For standard creatives, maps 1:1 with the creative itself.", + "type": "object", + "allOf": [ + { + "title": "Delivery Metrics", + "description": "Standard delivery metrics that can be reported at media buy, package, or creative level", + "type": "object", + "properties": { + "impressions": { + "type": "number", + "description": "Impressions delivered", + "minimum": 0 + }, + "spend": { + "type": "number", + "description": "Amount spent", + "minimum": 0 + }, + "clicks": { + "type": "number", + "description": "Total clicks", + "minimum": 0 + }, + "ctr": { + "type": "number", + "description": "Click-through rate (clicks/impressions)", + "minimum": 0, + "maximum": 1 + }, + "views": { + "type": "number", + "description": "Views at threshold (for CPV)", + "minimum": 0 + }, + "completed_views": { + "type": "number", + "description": "Video/audio completions. When the package has a completed_views optimization goal with view_duration_seconds, completions are counted at that threshold rather than 100% completion.", + "minimum": 0 + }, + "completion_rate": { + "type": "number", + "description": "Completion rate (completed_views/impressions)", + "minimum": 0, + "maximum": 1 + }, + "conversions": { + "type": "number", + "description": "Total conversions attributed to this delivery. When by_event_type is present, this equals the sum of all by_event_type[].count entries.", + "minimum": 0 + }, + "conversion_value": { + "type": "number", + "description": "Total monetary value of attributed conversions (in the reporting currency)", + "minimum": 0 + }, + "roas": { + "type": "number", + "description": "Return on ad spend (conversion_value / spend)", + "minimum": 0 + }, + "cost_per_acquisition": { + "type": "number", + "description": "Cost per conversion (spend / conversions)", + "minimum": 0 + }, + "new_to_brand_rate": { + "type": "number", + "description": "Fraction of conversions from first-time brand buyers (0 = none, 1 = all)", + "minimum": 0, + "maximum": 1 + }, + "leads": { + "type": "number", + "description": "Leads generated (convenience alias for by_event_type where event_type='lead')", + "minimum": 0 + }, + "by_event_type": { + "type": "array", + "description": "Conversion metrics broken down by event type. Spend-derived metrics (ROAS, CPA) are only available at the package/totals level since spend cannot be attributed to individual event types.", + "items": { + "type": "object", + "properties": { + "event_type": { + "title": "Event Type", + "description": "The event type", + "type": "string", + "enum": [ + "page_view", + "view_content", + "select_content", + "select_item", + "search", + "share", + "add_to_cart", + "remove_from_cart", + "viewed_cart", + "add_to_wishlist", + "initiate_checkout", + "add_payment_info", + "purchase", + "refund", + "lead", + "qualify_lead", + "close_convert_lead", + "disqualify_lead", + "complete_registration", + "subscribe", + "start_trial", + "app_install", + "app_launch", + "contact", + "schedule", + "donate", + "submit_application", + "custom" + ], + "enumDescriptions": { + "page_view": "User viewed a page", + "view_content": "User viewed specific content (product, article, etc.)", + "select_content": "User selected or clicked on content (article, video, etc.)", + "select_item": "User selected a specific product or item from a list", + "search": "User performed a search", + "share": "User shared content via social or messaging", + "add_to_cart": "User added an item to cart", + "remove_from_cart": "User removed an item from cart", + "viewed_cart": "User viewed their shopping cart", + "add_to_wishlist": "User added an item to a wishlist", + "initiate_checkout": "User started checkout process", + "add_payment_info": "User added payment information", + "purchase": "User completed a purchase", + "refund": "A purchase was fully or partially refunded (adjusts ROAS)", + "lead": "User expressed interest (form submission, signup, etc.)", + "qualify_lead": "Lead qualified by sales or scoring criteria", + "close_convert_lead": "Lead converted to a customer or closed deal", + "disqualify_lead": "Lead disqualified or marked as not viable", + "complete_registration": "User completed account registration", + "subscribe": "User subscribed to a service or newsletter", + "start_trial": "User started a free trial", + "app_install": "User installed an application", + "app_launch": "User launched an application", + "contact": "User initiated contact (call, message, etc.)", + "schedule": "User scheduled an appointment or event", + "donate": "User made a donation", + "submit_application": "User submitted an application (loan, job, etc.)", + "custom": "Custom event type (specify in custom_event_name)" + } + }, + "event_source_id": { + "type": "string", + "description": "Event source that produced these conversions (for disambiguation when multiple event sources are configured)" + }, + "count": { + "type": "number", + "description": "Number of events of this type", + "minimum": 0 + }, + "value": { + "type": "number", + "description": "Total monetary value of events of this type", + "minimum": 0 + } + }, + "required": [ + "event_type", + "count" + ], + "additionalProperties": true + } + }, + "grps": { + "type": "number", + "description": "Gross Rating Points delivered (for CPP)", + "minimum": 0 + }, + "reach": { + "type": "number", + "description": "Unique reach - units depend on measurement provider (e.g., individuals, households, devices, cookies). See delivery_measurement.provider for methodology.", + "minimum": 0 + }, + "frequency": { + "type": "number", + "description": "Average frequency per individual (typically measured over campaign duration, but can vary by measurement provider)", + "minimum": 0 + }, + "quartile_data": { + "type": "object", + "description": "Video quartile completion data", + "properties": { + "q1_views": { + "type": "number", + "description": "25% completion views", + "minimum": 0 + }, + "q2_views": { + "type": "number", + "description": "50% completion views", + "minimum": 0 + }, + "q3_views": { + "type": "number", + "description": "75% completion views", + "minimum": 0 + }, + "q4_views": { + "type": "number", + "description": "100% completion views", + "minimum": 0 + } + } + }, + "dooh_metrics": { + "type": "object", + "description": "DOOH-specific metrics (only included for DOOH campaigns)", + "properties": { + "loop_plays": { + "type": "integer", + "description": "Number of times ad played in rotation", + "minimum": 0 + }, + "screens_used": { + "type": "integer", + "description": "Number of unique screens displaying the ad", + "minimum": 0 + }, + "screen_time_seconds": { + "type": "integer", + "description": "Total display time in seconds", + "minimum": 0 + }, + "sov_achieved": { + "type": "number", + "description": "Actual share of voice delivered (0.0 to 1.0)", + "minimum": 0, + "maximum": 1 + }, + "calculation_notes": { + "type": "string", + "description": "Explanation of how DOOH impressions were calculated" + }, + "venue_breakdown": { + "type": "array", + "description": "Per-venue performance breakdown", + "items": { + "type": "object", + "properties": { + "venue_id": { + "type": "string", + "description": "Venue identifier" + }, + "venue_name": { + "type": "string", + "description": "Human-readable venue name" + }, + "venue_type": { + "type": "string", + "description": "Venue type (e.g., 'airport', 'transit', 'retail', 'billboard')" + }, + "impressions": { + "type": "integer", + "description": "Impressions delivered at this venue", + "minimum": 0 + }, + "loop_plays": { + "type": "integer", + "description": "Loop plays at this venue", + "minimum": 0 + }, + "screens_used": { + "type": "integer", + "description": "Number of screens used at this venue", + "minimum": 0 + } + }, + "required": [ + "venue_id", + "impressions" + ], + "additionalProperties": true + } + } + }, + "additionalProperties": true + }, + "viewability": { + "type": "object", + "description": "Viewability metrics. Viewable rate should be calculated as viewable_impressions / measurable_impressions (not total impressions), since some environments cannot measure viewability.", + "properties": { + "measurable_impressions": { + "type": "number", + "description": "Impressions where viewability could be measured. Excludes environments without measurement capability (e.g., non-Intersection Observer browsers, certain app environments).", + "minimum": 0 + }, + "viewable_impressions": { + "type": "number", + "description": "Impressions that met the viewability threshold defined by the measurement standard.", + "minimum": 0 + }, + "viewable_rate": { + "type": "number", + "description": "Viewable impression rate (viewable_impressions / measurable_impressions). Range 0.0 to 1.0.", + "minimum": 0, + "maximum": 1 + }, + "standard": { + "type": "string", + "enum": [ + "mrc", + "groupm" + ], + "description": "Viewability measurement standard. 'mrc': 50% of pixels in view for 1 second (display) or 2 seconds (video), per MRC/IAB guidelines. 'groupm': 100% of pixels in view for the same durations. These are materially different thresholds and should not be compared across standards." + } + }, + "additionalProperties": true + }, + "engagements": { + "type": "number", + "description": "Total engagements — direct interactions with the ad beyond viewing. Includes social reactions/comments/shares, story/unit opens, interactive overlay taps on CTV, companion banner interactions on audio. Platform-specific; corresponds to the 'engagements' optimization metric.", + "minimum": 0 + }, + "follows": { + "type": "number", + "description": "New followers, page likes, artist/podcast/channel subscribes attributed to this delivery.", + "minimum": 0 + }, + "saves": { + "type": "number", + "description": "Saves, bookmarks, playlist adds, pins attributed to this delivery.", + "minimum": 0 + }, + "profile_visits": { + "type": "number", + "description": "Visits to the brand's in-platform page (profile, artist page, channel, or storefront) attributed to this delivery. Does not include external website clicks.", + "minimum": 0 + }, + "engagement_rate": { + "type": "number", + "description": "Platform-specific engagement rate (0.0 to 1.0). Typically engagements/impressions, but definition varies by platform.", + "minimum": 0, + "maximum": 1 + }, + "cost_per_click": { + "type": "number", + "description": "Cost per click (spend / clicks)", + "minimum": 0 + }, + "by_action_source": { + "type": "array", + "description": "Conversion metrics broken down by action source (website, app, in_store, etc.). Useful for omnichannel sellers where conversions occur across digital and physical channels.", + "items": { + "type": "object", + "properties": { + "action_source": { + "title": "Action Source", + "description": "Where the conversion occurred", + "type": "string", + "enum": [ + "website", + "app", + "offline", + "phone_call", + "chat", + "email", + "in_store", + "system_generated", + "other" + ], + "enumDescriptions": { + "website": "Event occurred on a website", + "app": "Event occurred in a mobile or desktop app", + "offline": "Event occurred offline (imported data)", + "phone_call": "Event originated from a phone call", + "chat": "Event originated from a chat conversation", + "email": "Event originated from an email interaction", + "in_store": "Event occurred at a physical retail location", + "system_generated": "Event generated by an automated system", + "other": "Other source (specify in ext)" + } + }, + "event_source_id": { + "type": "string", + "description": "Event source that produced these conversions (for disambiguation when multiple event sources are configured)" + }, + "count": { + "type": "number", + "description": "Number of conversions from this action source", + "minimum": 0 + }, + "value": { + "type": "number", + "description": "Total monetary value of conversions from this action source", + "minimum": 0 + } + }, + "required": [ + "action_source", + "count" + ], + "additionalProperties": true + } + } + }, + "additionalProperties": true + }, + { + "properties": { + "variant_id": { + "type": "string", + "description": "Platform-assigned identifier for this variant" + }, + "manifest": { + "title": "Creative Manifest", + "description": "The rendered creative manifest for this variant — the actual output that was served, not the input assets. Contains format_id and the resolved assets (specific headline, image, video, etc. the platform selected or generated). For Tier 2, shows which asset combination was picked. For Tier 3, contains the generated assets which may differ entirely from the input brand identity. Pass to preview_creative to re-render.", + "type": "object", + "properties": { + "format_id": { + "title": "Format ID", + "description": "Format identifier this manifest is for. Can be a template format (id only) or a deterministic format (id + dimensions/duration). For dimension-specific creatives, include width/height/unit in the format_id to create a unique identifier (e.g., {id: 'display_static', width: 300, height: 250, unit: 'px'}).", + "type": "object", + "properties": { + "agent_url": { + "type": "string", + "format": "uri", + "description": "URL of the agent that defines this format (e.g., 'https://creatives.adcontextprotocol.org' for standard formats, or 'https://publisher.com/.well-known/adcp/sales' for custom formats)" + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]+$", + "description": "Format identifier within the agent's namespace (e.g., 'display_static', 'video_hosted', 'audio_standard'). When used alone, references a template format. When combined with dimension/duration fields, creates a parameterized format ID for a specific variant." + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels for visual formats. When specified, height must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels for visual formats. When specified, width must also be specified. Both fields together create a parameterized format ID for dimension-specific variants." + }, + "duration_ms": { + "type": "number", + "minimum": 1, + "description": "Duration in milliseconds for time-based formats (video, audio). When specified, creates a parameterized format ID. Omit to reference a template format without parameters." + } + }, + "required": [ + "agent_url", + "id" + ], + "additionalProperties": true, + "dependencies": { + "width": [ + "height" + ], + "height": [ + "width" + ] + } + }, + "catalogs": { + "type": "array", + "description": "Catalogs this creative renders. Each entry satisfies one of the format's catalog_requirements, matched by type. Tells the creative what data to display — product listings for a carousel, job vacancies for a recruitment ad, store locations for a locator. This is a data reference, not a campaign expansion directive; campaign structure and budget allocation are handled by create_media_buy packages. Each catalog can be inline (with items), a reference to a synced catalog (by catalog_id), or a URL to an external feed.", + "items": { + "title": "Catalog", + "description": "A typed data feed. Catalogs carry the items, locations, stock levels, or pricing that publishers use to render ads. They can be synced to a platform via sync_catalogs (managed lifecycle with approval), provided inline, or fetched from an external URL. The catalog type determines the item schema and can be structural (offering, product, inventory, store, promotion) or vertical-specific (hotel, flight, job, vehicle, real_estate, education, destination, app). Selectors (ids, tags, category, query) filter items regardless of sourcing method.", + "type": "object", + "properties": { + "catalog_id": { + "type": "string", + "description": "Buyer's identifier for this catalog. Required when syncing via sync_catalogs. When used in creatives, references a previously synced catalog on the account." + }, + "name": { + "type": "string", + "description": "Human-readable name for this catalog (e.g., 'Summer Products 2025', 'Amsterdam Store Locations')." + }, + "type": { + "title": "Catalog Type", + "description": "Catalog type. Structural types: 'offering' (AdCP Offering objects), 'product' (ecommerce entries), 'inventory' (stock per location), 'store' (physical locations), 'promotion' (deals and pricing). Vertical types: 'hotel', 'flight', 'job', 'vehicle', 'real_estate', 'education', 'destination', 'app' — each with an industry-specific item schema.", + "type": "string", + "enum": [ + "offering", + "product", + "inventory", + "store", + "promotion", + "hotel", + "flight", + "job", + "vehicle", + "real_estate", + "education", + "destination", + "app" + ] + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL to an external catalog feed. The platform fetches and resolves items from this URL. For offering-type catalogs, the feed contains an array of Offering objects. For other types, the feed format is determined by feed_format. When omitted with type 'product', the platform uses its synced copy of the brand's product catalog." + }, + "feed_format": { + "title": "Feed Format", + "description": "Format of the external feed at url. Required when url points to a non-AdCP feed (e.g., Google Merchant Center XML, Meta Product Catalog). Omit for offering-type catalogs where the feed is native AdCP JSON.", + "type": "string", + "enum": [ + "google_merchant_center", + "facebook_catalog", + "shopify", + "linkedin_jobs", + "custom" + ] + }, + "update_frequency": { + "title": "Update Frequency", + "description": "How often the platform should re-fetch the feed from url. Only applicable when url is provided. Platforms may use this as a hint for polling schedules.", + "type": "string", + "enum": [ + "realtime", + "hourly", + "daily", + "weekly" + ] + }, + "items": { + "type": "array", + "description": "Inline catalog data. The item schema depends on the catalog type: Offering objects for 'offering', StoreItem for 'store', HotelItem for 'hotel', FlightItem for 'flight', JobItem for 'job', VehicleItem for 'vehicle', RealEstateItem for 'real_estate', EducationItem for 'education', DestinationItem for 'destination', AppItem for 'app', or freeform objects for 'product', 'inventory', and 'promotion'. Mutually exclusive with url — provide one or the other, not both. Implementations should validate items against the type-specific schema.", + "items": { + "type": "object" + }, + "minItems": 1 + }, + "ids": { + "type": "array", + "description": "Filter catalog to specific item IDs. For offering-type catalogs, these are offering_id values. For product-type catalogs, these are SKU identifiers.", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "gtins": { + "type": "array", + "description": "Filter product-type catalogs by GTIN identifiers for cross-retailer catalog matching. Accepts standard GTIN formats (GTIN-8, UPC-A/GTIN-12, EAN-13/GTIN-13, GTIN-14). Only applicable when type is 'product'.", + "items": { + "type": "string", + "pattern": "^[0-9]{8,14}$" + }, + "minItems": 1 + }, + "tags": { + "type": "array", + "description": "Filter catalog to items with these tags. Tags are matched using OR logic — items matching any tag are included.", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "category": { + "type": "string", + "description": "Filter catalog to items in this category (e.g., 'beverages/soft-drinks', 'chef-positions')." + }, + "query": { + "type": "string", + "description": "Natural language filter for catalog items (e.g., 'all pasta sauces under $5', 'amsterdam vacancies')." + }, + "conversion_events": { + "type": "array", + "description": "Event types that represent conversions for items in this catalog. Declares what events the platform should attribute to catalog items — e.g., a job catalog converts via submit_application, a product catalog via purchase. The event's content_ids field carries the item IDs that connect back to catalog items. Use content_id_type to declare what identifier type content_ids values represent.", + "items": { + "title": "Event Type", + "description": "Standard marketing event types for event logging, aligned with IAB ECAPI", + "type": "string", + "enum": [ + "page_view", + "view_content", + "select_content", + "select_item", + "search", + "share", + "add_to_cart", + "remove_from_cart", + "viewed_cart", + "add_to_wishlist", + "initiate_checkout", + "add_payment_info", + "purchase", + "refund", + "lead", + "qualify_lead", + "close_convert_lead", + "disqualify_lead", + "complete_registration", + "subscribe", + "start_trial", + "app_install", + "app_launch", + "contact", + "schedule", + "donate", + "submit_application", + "custom" + ], + "enumDescriptions": { + "page_view": "User viewed a page", + "view_content": "User viewed specific content (product, article, etc.)", + "select_content": "User selected or clicked on content (article, video, etc.)", + "select_item": "User selected a specific product or item from a list", + "search": "User performed a search", + "share": "User shared content via social or messaging", + "add_to_cart": "User added an item to cart", + "remove_from_cart": "User removed an item from cart", + "viewed_cart": "User viewed their shopping cart", + "add_to_wishlist": "User added an item to a wishlist", + "initiate_checkout": "User started checkout process", + "add_payment_info": "User added payment information", + "purchase": "User completed a purchase", + "refund": "A purchase was fully or partially refunded (adjusts ROAS)", + "lead": "User expressed interest (form submission, signup, etc.)", + "qualify_lead": "Lead qualified by sales or scoring criteria", + "close_convert_lead": "Lead converted to a customer or closed deal", + "disqualify_lead": "Lead disqualified or marked as not viable", + "complete_registration": "User completed account registration", + "subscribe": "User subscribed to a service or newsletter", + "start_trial": "User started a free trial", + "app_install": "User installed an application", + "app_launch": "User launched an application", + "contact": "User initiated contact (call, message, etc.)", + "schedule": "User scheduled an appointment or event", + "donate": "User made a donation", + "submit_application": "User submitted an application (loan, job, etc.)", + "custom": "Custom event type (specify in custom_event_name)" + } + }, + "minItems": 1, + "uniqueItems": true + }, + "content_id_type": { + "title": "Content ID Type", + "description": "Identifier type that the event's content_ids field should be matched against for items in this catalog. For example, 'gtin' means content_ids values are Global Trade Item Numbers, 'sku' means retailer SKUs. Omit when using a custom identifier scheme not listed in the enum.", + "type": "string", + "enum": [ + "sku", + "gtin", + "offering_id", + "job_id", + "hotel_id", + "flight_id", + "vehicle_id", + "listing_id", + "store_id", + "program_id", + "destination_id", + "app_id" + ] + }, + "feed_field_mappings": { + "type": "array", + "description": "Declarative normalization rules for external feeds. Maps non-standard feed field names, date formats, price encodings, and image URLs to the AdCP catalog item schema. Applied during sync_catalogs ingestion. Supports field renames, named transforms (date, divide, boolean, split), static literal injection, and assignment of image URLs to typed asset pools.", + "items": { + "title": "Catalog Field Mapping", + "description": "Declares how a field in an external feed maps to the AdCP catalog item schema. Used in sync_catalogs feed_field_mappings to normalize non-AdCP feeds (Google Merchant Center, LinkedIn Jobs XML, hotel XML, etc.) to the standard catalog item schema without requiring the buyer to preprocess every feed. Multiple mappings can assemble a nested object via dot notation (e.g., separate mappings for price.amount and price.currency).", + "type": "object", + "properties": { + "feed_field": { + "type": "string", + "description": "Field name in the external feed record. Omit when injecting a static literal value (use the value property instead)." + }, + "catalog_field": { + "type": "string", + "description": "Target field on the catalog item schema, using dot notation for nested fields (e.g., 'name', 'price.amount', 'location.city'). Mutually exclusive with asset_group_id." + }, + "asset_group_id": { + "type": "string", + "description": "Places the feed field value (a URL) into a typed asset pool on the catalog item's assets array. The value is wrapped as an image or video asset in a group with this ID. Use standard group IDs: 'images_landscape', 'images_vertical', 'images_square', 'logo', 'video'. Mutually exclusive with catalog_field." + }, + "value": { + "description": "Static literal value to inject into catalog_field for every item, regardless of what the feed contains. Mutually exclusive with feed_field. Useful for fields the feed omits (e.g., currency when price is always USD, or a constant category value)." + }, + "transform": { + "type": "string", + "description": "Named transform to apply to the feed field value before writing to the catalog schema. See transform-specific parameters (format, timezone, by, separator).", + "enum": [ + "date", + "divide", + "boolean", + "split" + ] + }, + "format": { + "type": "string", + "description": "For transform 'date': the input date format string (e.g., 'YYYYMMDD', 'MM/DD/YYYY', 'DD-MM-YYYY'). Output is always ISO 8601 (e.g., '2025-03-01'). Uses Unicode date pattern tokens." + }, + "timezone": { + "type": "string", + "description": "For transform 'date': the timezone of the input value. IANA timezone identifier (e.g., 'UTC', 'America/New_York', 'Europe/Amsterdam'). Defaults to UTC when omitted." + }, + "by": { + "type": "number", + "description": "For transform 'divide': the divisor to apply (e.g., 100 to convert integer cents to decimal dollars).", + "exclusiveMinimum": 0 + }, + "separator": { + "type": "string", + "description": "For transform 'split': the separator character or string to split on. Defaults to ','.", + "default": "," + }, + "default": { + "description": "Fallback value to use when feed_field is absent, null, or empty. Applied after any transform would have been applied. Allows optional feed fields to have a guaranteed baseline value." + }, + "ext": { + "title": "Extension Object", + "description": "Extension object for platform-specific, vendor-namespaced parameters. Extensions are always optional and must be namespaced under a vendor/platform key (e.g., ext.gam, ext.roku). Used for custom capabilities, partner-specific configuration, and features being proposed for standardization.", + "type": "object", + "additionalProperties": true + } + }, + "allOf": [ + { + "not": { + "required": [ + "feed_field", + "value" + ] + } + }, + { + "not": { + "required": [ + "catalog_field", + "asset_group_id" + ] + } + } + ], + "additionalProperties": true, + "examples": [ + { + "description": "Simple field rename", + "data": { + "feed_field": "hotel_name", + "catalog_field": "name" + } + }, + { + "description": "Date format transform — YYYYMMDD to ISO 8601", + "data": { + "feed_field": "available_from", + "catalog_field": "valid_from", + "transform": "date", + "format": "YYYYMMDD", + "timezone": "UTC" + } + }, + { + "description": "Divide cents to dollars", + "data": { + "feed_field": "price_cents", + "catalog_field": "price.amount", + "transform": "divide", + "by": 100 + } + }, + { + "description": "Static literal injection — currency not in feed", + "data": { + "catalog_field": "price.currency", + "value": "USD" + } + }, + { + "description": "Image URL assigned to typed asset pool", + "data": { + "feed_field": "primary_photo_url", + "asset_group_id": "images_landscape" + } + }, + { + "description": "Vertical photo URL assigned to vertical pool", + "data": { + "feed_field": "portrait_photo_url", + "asset_group_id": "images_vertical" + } + }, + { + "description": "Split comma-separated tags to array", + "data": { + "feed_field": "amenity_list", + "catalog_field": "amenities", + "transform": "split", + "separator": "," + } + }, + { + "description": "Boolean coercion with default", + "data": { + "feed_field": "is_available", + "catalog_field": "available", + "transform": "boolean", + "default": false + } + } + ] + }, + "minItems": 1 + } + }, + "required": [ + "type" + ], + "additionalProperties": true, + "examples": [ + { + "description": "Synced product catalog from Google Merchant Center", + "data": { + "catalog_id": "gmc-primary", + "name": "Primary Product Feed", + "type": "product", + "url": "https://feeds.acmecorp.com/products.xml", + "feed_format": "google_merchant_center", + "update_frequency": "daily" + } + }, + { + "description": "Inventory feed for store-level stock data", + "data": { + "catalog_id": "store-inventory", + "name": "Store Inventory", + "type": "inventory", + "url": "https://feeds.acmecorp.com/inventory.json", + "feed_format": "custom", + "update_frequency": "hourly" + } + }, + { + "description": "Store locator feed", + "data": { + "catalog_id": "retail-locations", + "name": "Retail Locations", + "type": "store", + "url": "https://feeds.acmecorp.com/stores.json", + "feed_format": "custom", + "update_frequency": "weekly" + } + }, + { + "description": "Promotional pricing feed", + "data": { + "catalog_id": "summer-sale", + "name": "Summer Sale Promotions", + "type": "promotion", + "url": "https://feeds.acmecorp.com/promotions.json", + "feed_format": "google_merchant_center", + "update_frequency": "daily" + } + }, + { + "description": "Inline offering catalog (no sync needed)", + "data": { + "type": "offering", + "items": [ + { + "offering_id": "summer-sale", + "name": "Summer Sale", + "landing_url": "https://acme.com/summer" + } + ] + } + }, + { + "description": "Reference to a previously synced catalog by ID", + "data": { + "catalog_id": "gmc-primary", + "type": "product", + "ids": [ + "SKU-12345", + "SKU-67890" + ] + } + }, + { + "description": "Product catalog with GTIN cross-retailer matching and attribution", + "data": { + "type": "product", + "gtins": [ + "00013000006040", + "00013000006057" + ], + "content_id_type": "gtin", + "conversion_events": [ + "purchase", + "add_to_cart" + ] + } + }, + { + "description": "Inline store catalog with catchment areas", + "data": { + "catalog_id": "retail-locations", + "name": "Retail Locations", + "type": "store", + "items": [ + { + "store_id": "amsterdam-flagship", + "name": "Amsterdam Flagship", + "location": { + "lat": 52.3676, + "lng": 4.9041 + }, + "catchments": [ + { + "catchment_id": "walk", + "travel_time": { + "value": 10, + "unit": "min" + }, + "transport_mode": "walking" + }, + { + "catchment_id": "drive", + "travel_time": { + "value": 15, + "unit": "min" + }, + "transport_mode": "driving" + } + ] + } + ] + } + } + ] + }, + "minItems": 1 + }, + "assets": { + "type": "object", + "description": "Map of asset IDs to actual asset content. Each key MUST match an asset_id from the format's assets array (e.g., 'banner_image', 'clickthrough_url', 'video_file', 'vast_tag'). The asset_id is the technical identifier used to match assets to format requirements.\n\nIMPORTANT: Full validation requires format context. The format defines what type each asset_id should be. Standalone schema validation only checks structural conformance — each asset must match at least one valid asset type schema.", + "patternProperties": { + "^[a-z0-9_]+$": { + "anyOf": [ + { + "title": "Image Asset", + "description": "Image asset with URL and dimensions", + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL to the image asset" + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels" + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels" + }, + "format": { + "type": "string", + "description": "Image file format (jpg, png, gif, webp, etc.)" + }, + "alt_text": { + "type": "string", + "description": "Alternative text for accessibility", + "x-accessibility": true + } + }, + "required": [ + "url", + "width", + "height" + ], + "additionalProperties": true + }, + { + "title": "Video Asset", + "description": "Video asset with URL and technical specifications including audio track properties", + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL to the video asset" + }, + "width": { + "type": "integer", + "minimum": 1, + "description": "Width in pixels" + }, + "height": { + "type": "integer", + "minimum": 1, + "description": "Height in pixels" + }, + "duration_ms": { + "type": "integer", + "description": "Video duration in milliseconds", + "minimum": 1 + }, + "file_size_bytes": { + "type": "integer", + "description": "File size in bytes", + "minimum": 1 + }, + "container_format": { + "type": "string", + "description": "Video container format (mp4, webm, mov, etc.)" + }, + "video_codec": { + "type": "string", + "description": "Video codec used (h264, h265, vp9, av1, prores, etc.)" + }, + "video_bitrate_kbps": { + "type": "integer", + "description": "Video stream bitrate in kilobits per second", + "minimum": 1 + }, + "frame_rate": { + "type": "string", + "description": "Frame rate as string to preserve precision (e.g., '23.976', '29.97', '30')" + }, + "frame_rate_type": { + "type": "string", + "enum": [ + "constant", + "variable" + ], + "description": "Whether the video uses constant (CFR) or variable (VFR) frame rate" + }, + "scan_type": { + "type": "string", + "enum": [ + "progressive", + "interlaced" + ], + "description": "Scan type of the video" + }, + "color_space": { + "type": "string", + "enum": [ + "rec709", + "rec2020", + "rec2100", + "srgb", + "dci_p3" + ], + "description": "Color space of the video" + }, + "hdr_format": { + "type": "string", + "enum": [ + "sdr", + "hdr10", + "hdr10_plus", + "hlg", + "dolby_vision" + ], + "description": "HDR format if applicable, or 'sdr' for standard dynamic range" + }, + "chroma_subsampling": { + "type": "string", + "enum": [ + "4:2:0", + "4:2:2", + "4:4:4" + ], + "description": "Chroma subsampling format" + }, + "video_bit_depth": { + "type": "integer", + "enum": [ + 8, + 10, + 12 + ], + "description": "Video bit depth" + }, + "gop_interval_seconds": { + "type": "number", + "description": "GOP/keyframe interval in seconds" + }, + "gop_type": { + "type": "string", + "enum": [ + "closed", + "open" + ], + "description": "GOP structure type" + }, + "moov_atom_position": { + "type": "string", + "enum": [ + "start", + "end" + ], + "description": "Position of moov atom in MP4 container" + }, + "has_audio": { + "type": "boolean", + "description": "Whether the video contains an audio track" + }, + "audio_codec": { + "type": "string", + "description": "Audio codec used (aac, aac_lc, he_aac, pcm, mp3, ac3, eac3, etc.)" + }, + "audio_sampling_rate_hz": { + "type": "integer", + "description": "Audio sampling rate in Hz (e.g., 44100, 48000)" + }, + "audio_channels": { + "type": "string", + "enum": [ + "mono", + "stereo", + "5.1", + "7.1" + ], + "description": "Audio channel configuration" + }, + "audio_bit_depth": { + "type": "integer", + "enum": [ + 16, + 24, + 32 + ], + "description": "Audio bit depth" + }, + "audio_bitrate_kbps": { + "type": "integer", + "description": "Audio bitrate in kilobits per second", + "minimum": 1 + }, + "audio_loudness_lufs": { + "type": "number", + "description": "Integrated loudness in LUFS" + }, + "audio_true_peak_dbfs": { + "type": "number", + "description": "True peak level in dBFS" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the video content", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + } + }, + "required": [ + "url", + "width", + "height" + ], + "additionalProperties": true + }, + { + "title": "Audio Asset", + "description": "Audio asset with URL and technical specifications", + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL to the audio asset" + }, + "duration_ms": { + "type": "integer", + "description": "Audio duration in milliseconds", + "minimum": 0 + }, + "file_size_bytes": { + "type": "integer", + "description": "File size in bytes", + "minimum": 1 + }, + "container_format": { + "type": "string", + "description": "Audio container/file format (mp3, m4a, aac, wav, ogg, flac, etc.)" + }, + "codec": { + "type": "string", + "description": "Audio codec used (aac, aac_lc, he_aac, pcm, mp3, vorbis, opus, flac, ac3, eac3, etc.)" + }, + "sampling_rate_hz": { + "type": "integer", + "description": "Sampling rate in Hz (e.g., 44100, 48000, 96000)" + }, + "channels": { + "type": "string", + "enum": [ + "mono", + "stereo", + "5.1", + "7.1" + ], + "description": "Channel configuration" + }, + "bit_depth": { + "type": "integer", + "enum": [ + 16, + 24, + 32 + ], + "description": "Bit depth" + }, + "bitrate_kbps": { + "type": "integer", + "description": "Bitrate in kilobits per second", + "minimum": 1 + }, + "loudness_lufs": { + "type": "number", + "description": "Integrated loudness in LUFS" + }, + "true_peak_dbfs": { + "type": "number", + "description": "True peak level in dBFS" + }, + "transcript_url": { + "type": "string", + "format": "uri", + "description": "URL to text transcript of the audio content", + "x-accessibility": true + } + }, + "required": [ + "url" + ], + "additionalProperties": true + }, + { + "title": "VAST Asset", + "description": "VAST (Video Ad Serving Template) tag for third-party video ad serving", + "oneOf": [ + { + "type": "object", + "properties": { + "delivery_type": { + "type": "string", + "const": "url", + "description": "Discriminator indicating VAST is delivered via URL endpoint" + }, + "url": { + "type": "string", + "format": "uri", + "description": "URL endpoint that returns VAST XML" + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Standard VAST tracking events for video ad playback and interaction", + "type": "string", + "enum": [ + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "impression", + "click", + "pause", + "resume", + "skip", + "mute", + "unmute", + "fullscreen", + "exitFullscreen", + "playerExpand", + "playerCollapse" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + } + }, + "required": [ + "delivery_type", + "url" + ], + "additionalProperties": true + }, + { + "type": "object", + "properties": { + "delivery_type": { + "type": "string", + "const": "inline", + "description": "Discriminator indicating VAST is delivered as inline XML content" + }, + "content": { + "type": "string", + "description": "Inline VAST XML content" + }, + "vast_version": { + "title": "VAST Version", + "description": "VAST specification version", + "type": "string", + "enum": [ + "2.0", + "3.0", + "4.0", + "4.1", + "4.2" + ] + }, + "vpaid_enabled": { + "type": "boolean", + "description": "Whether VPAID (Video Player-Ad Interface Definition) is supported" + }, + "duration_ms": { + "type": "integer", + "description": "Expected video duration in milliseconds (if known)", + "minimum": 0 + }, + "tracking_events": { + "type": "array", + "items": { + "title": "VAST Tracking Event", + "description": "Standard VAST tracking events for video ad playback and interaction", + "type": "string", + "enum": [ + "start", + "firstQuartile", + "midpoint", + "thirdQuartile", + "complete", + "impression", + "click", + "pause", + "resume", + "skip", + "mute", + "unmute", + "fullscreen", + "exitFullscreen", + "playerExpand", + "playerCollapse" + ] + }, + "description": "Tracking events supported by this VAST tag" + }, + "captions_url": { + "type": "string", + "format": "uri", + "description": "URL to captions file (WebVTT, SRT, etc.)", + "x-accessibility": true + }, + "audio_description_url": { + "type": "string", + "format": "uri", + "description": "URL to audio description track for visually impaired users", + "x-accessibility": true + } + }, + "required": [ + "delivery_type", + "content" + ], + "additionalProperties": true + } + ] + }, + { + "title": "Text Asset", + "description": "Text content asset", + "type": "object", + "properties": { + "content": { + "type": "string", + "description": "Text content" + }, + "language": { + "type": "string", + "description": "Language code (e.g., 'en', 'es', 'fr')" + } + }, + "required": [ + "content" + ], + "additionalProperties": true + }, + { + "title": "URL Asset", + "description": "URL reference asset", + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL reference" + }, + "url_type": { + "title": "URL Asset Type", + "description": "Type of URL asset: 'clickthrough' for user click destination (landing page), 'tracker_pixel' for impression/event tracking via HTTP request (fires GET, expects pixel/204 response), 'tracker_script' for measurement SDKs that must load as