> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adcontextprotocol.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Video Ads

> Canonical hosted-video and VAST creative contracts for AdCP 3.2.

AdCP separates hosted video bytes (`video_hosted`) from VAST delivery (`video_vast`). Placement position such as pre-roll or mid-roll belongs on the product/placement, while the creative declaration describes the accepted payload.

## Hosted video

```json theme={null}
{
  "format_option_id": "preroll_30s_hosted",
  "format_kind": "video_hosted",
  "params": {
    "width": 1920,
    "height": 1080,
    "duration_ms_exact": 30000,
    "containers": ["mp4"],
    "video_codecs": ["h264"],
    "audio_codecs": ["aac"],
    "max_file_size_kb": 51200,
    "slots": [
      { "asset_group_id": "video_main", "asset_type": "video", "required": true },
      { "asset_group_id": "landing_page_url", "asset_type": "url", "required": false }
    ]
  }
}
```

```json theme={null}
{
  "format_kind": "video_hosted",
  "assets": {
    "video_main": {
      "asset_type": "video",
      "url": "https://cdn.acmeoutdoor.example/trail-pro-30s.mp4",
      "width": 1920,
      "height": 1080,
      "duration_ms": 30000,
      "container_format": "mp4",
      "codec": "h264"
    }
  }
}
```

## VAST

```json theme={null}
{
  "technical_requirements_complete": true,
  "format_kind": "video_vast",
  "params": {
    "duration_ms_range": [15000, 30000],
    "vast_versions": ["3.0", "4.0", "4.1", "4.2"],
    "media_file_requirements": {
      "delivery_methods": ["progressive"],
      "mime_types": ["video/mp4"],
      "containers": ["mp4"],
      "codecs": ["avc1.4d401f"],
      "min_width": 1280,
      "max_width": 1920,
      "min_height": 720,
      "max_height": 1080,
      "min_bitrate_kbps": 1500,
      "max_bitrate_kbps": 8000,
      "max_file_size_bytes": 50000000
    },
    "slots": [{ "asset_group_id": "vast_tag", "asset_type": "vast", "required": true }]
  }
}
```

Use a `vast` asset with either a URL or inline XML according to the selected declaration. The asset's singular `vast_version` is the exact version it supplies. The format option's plural `vast_versions` is the accepted set for that product/player path; seller-wide `execution.creative_specs.vast_versions` is only a ceiling.

Version compatibility is the intersection:

```text theme={null}
asset.vast_version
  ∈ product.format_option.params.vast_versions
  ∩ seller.execution.creative_specs.vast_versions
```

For example, a seller may advertise a platform ceiling through VAST 4.2 while one product accepts only VAST 3.0 and 4.0. The product set wins for that product. Never relabel an asset to a newer version merely because the destination supports it.

For ordinary legacy VAST submission, an omitted seller or product version set retains 3.x compatibility and document validation follows the peer's negotiated behavior. Late-bound `CreativeRepresentationSet` resolution is stricter: every VAST candidate declares `vast_version`, and both the selected product option and seller must advertise non-empty plural sets. Absence means compatibility is unproven, not “all versions.” During migration, producers emit either deprecated singular `vast_version` for older consumers or plural `vast_versions` for 3.2 consumers; the two fields are mutually exclusive so they cannot contradict one another.

### MediaFile technical acceptance

`params.media_file_requirements` describes the VAST player's accepted MediaFile renditions: delivery method (`progressive` or `streaming`), MIME type, container, codec, dimensions, bitrate, and maximum exact bytes. For each applicable resolved `<InLine>` linear creative, at least one `<MediaFile>` MUST satisfy every declared requirement. Requirements cannot be assembled across siblings: one progressive MP4 may satisfy the delivery, MIME, and codec constraints while a different streaming WebM satisfies the dimensions, but neither is compatible unless one rendition satisfies the full set. Other incompatible sibling renditions do not reject an otherwise compatible creative.

VAST metadata is the first source of evidence: `delivery`, `type`, `codec`, `width`, `height`, bitrate attributes, and `fileSize` where the applicable VAST version provides them. Fixed `bitrate` must fall within declared bounds; an adaptive `minBitrate`/`maxBitrate` interval must be fully contained by those bounds, not merely overlap them. A receiver MAY safely inspect referenced media bytes and MUST prefer the observed byte count if it conflicts with `fileSize`. It MUST NOT infer a container only from a URI filename extension. When metadata needed for a declared constraint is missing and safe inspection does not establish it, compatibility is unproven; the receiver does not guess.

Omitted MediaFile constraints follow the enclosing declaration's `technical_requirements_complete` value. When every applicable declaration layer asserts completeness, omission means no constraint and the seller cannot later reject a conforming creative for an unpublished delivery-method, MIME, container, codec, dimension, bitrate, or file-size rule. Without that complete assertion, omission means undeclared, not unlimited. `max_file_size_bytes` is always an exact byte count; elsewhere AdCP defines 1 KB as exactly 1,000 bytes and 1 MB as exactly 1,000,000 bytes.

### VAST Validation

Format-layer validation of `vast` assets is structural: the manifest must satisfy the format's plural accepted `vast_versions` set, and [`validate_input`](/dist/docs/3.2.0-beta.8/creative/canonical-formats#validation-flow--validate_input) checks manifest shape and declared compatibility. The VAST document itself is opaque at that level, so a structurally valid manifest can still carry an unplayable tag that fails at serve time.

AdCP defines three validation levels for `vast` assets. Sellers declare the level they perform via `creative_specs.vast_validation` in [`get_adcp_capabilities`](/dist/docs/3.2.0-beta.8/protocol/get_adcp_capabilities); absent means `structural`. Validation runs at `sync_creatives` time, including `dry_run`. `validate_input` remains manifest-structure-only at every level.

| Level                  | What the seller checks                                                             |
| ---------------------- | ---------------------------------------------------------------------------------- |
| `structural` (default) | Manifest shape and format `requirements` only. The VAST document is not inspected. |
| `document`             | Everything in `structural`, plus the VAST document itself.                         |
| `wrapper`              | Everything in `document`, plus wrapper-chain resolution.                           |

**Document-level validation.** Sellers declaring `document` or `wrapper`:

* MUST parse the document (inline `content`, or one response fetched from `url`) as XML and reject unparseable documents with `VAST_PARSE_FAILED` (`error.details.reason: "not_xml"`).
* MUST reject documents whose root element is not `<VAST>` with `VAST_PARSE_FAILED` (`error.details.reason: "no_vast_root"`).
* MUST reject the submitted document when its `<VAST version>` attribute is missing or differs from the asset's singular `vast_version`. The asset declaration describes this submitted URL response or inline document, not every later wrapper hop.
* MUST reject an asset whose `vast_version` is outside the product `params.vast_versions` and seller `creative_specs.vast_versions` intersection with `VAST_VERSION_MISMATCH`.
* MUST emit `mismatch_reason: "asset_outside_acceptance"`, `asset_vast_version`, `product_vast_versions`, and `seller_vast_versions` for an acceptance-set failure. Include `format_option_ref` only when the selected option is addressable; a unique id-less option has no reference to invent.
* MUST emit `mismatch_reason: "document_version_mismatch"`, `asset_vast_version`, raw `observed_document_vast_version`, and `document_role` when an inspected document violates its applicable version rule. For `wrapper` and `terminal_inline` roles, also emit `product_vast_versions` and `seller_vast_versions`, plus `format_option_ref` when the selected option is addressable, because those documents are compared with the acceptance intersection. Use `null` when the required version attribute is missing; preserve unknown/future strings verbatim for diagnosis. `supported_versions` remains a deprecated compatibility field for older 3.x peers.
* MUST make `VAST_VERSION_MISMATCH` details conform to [`error-details/vast-version-mismatch.json`](https://adcontextprotocol.org/schemas/3.2.0-beta.8/error-details/vast-version-mismatch.json).
* SHOULD reject documents containing no `<Ad>` element, and `<InLine>` linear creatives carrying no `<MediaFile>`, with `VAST_PARSE_FAILED` (`error.details.reason: "no_ad"` / `"no_media_file"`).
* MUST evaluate declared `media_file_requirements` against each applicable `<InLine>` linear creative and reject a creative for which no single `<MediaFile>` satisfies the full declared set. A document-level check evaluates the fetched document; wrapper-level validation evaluates the terminal resolved `<InLine>` document.
* SHOULD verify that media, tracking, and click URLs use HTTPS.
* MUST preserve undeclared macro tokens as opaque bytes. When an asset supplies `macro_declarations`, validate each token against the product and seller macro-resolution capability intersection and report per-token results.

**Wrapper-chain validation.** Sellers declaring `wrapper` additionally:

* MUST resolve `<Wrapper>` redirects via `<VASTAdTagURI>` up to the format's declared `max_wrapper_depth` (when present) and reject deeper chains with `VAST_WRAPPER_DEPTH_EXCEEDED` (`error.details.reason: "depth"`).
* MUST reject chains that revisit a `<VASTAdTagURI>` already seen (a loop) with `VAST_WRAPPER_DEPTH_EXCEEDED` (`error.details.reason: "loop"`).
* SHOULD apply a per-hop timeout, rejecting with `VAST_WRAPPER_DEPTH_EXCEEDED` (`error.details.reason: "timeout"`), and MUST fetch wrapper hops over HTTPS only.
* MUST parse every fetched wrapper and the terminal `<InLine>` document, and require each observed document version to be in the product/seller acceptance intersection. Only the submitted document is compared for equality with the asset's singular declaration; wrapper and terminal documents are not relabeled as the outer asset.

**Preflight, not approval.** A VAST endpoint can return a different document per request (decisioning, rotation, macros). Passing validation at sync time is a preflight of the tag's shape at that moment, not a guarantee about future responses. Sellers MUST NOT treat a passing preflight as approval of all future responses and MAY re-validate during delivery. Sellers fetching `url` assets or wrapper hops SHOULD apply the same server-side request protections (private-address blocking, redirect and size limits) they apply to any other agent-supplied URL fetch.

**Error codes.** In all cases `error.field` identifies the offending asset path in the manifest.

| Code                          | Meaning                                                                                                              |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `VAST_PARSE_FAILED`           | Document is not well-formed XML, has no `<VAST>` root, no `<Ad>`, or an inline linear creative has no `<MediaFile>`  |
| `VAST_VERSION_MISMATCH`       | Document version differs from the asset declaration, or the asset version is outside the product/seller intersection |
| `VAST_WRAPPER_DEPTH_EXCEEDED` | Wrapper chain exceeds `max_wrapper_depth`, loops, or a hop timed out                                                 |

## Vertical and flexible video

Vertical short video is still `video_hosted`; use width/height or aspect-ratio parameters and, for an exact publisher contract, `{publisher_domain, format_option_id}`. Equal canonical kind alone is not proof that a generic video builder satisfies a publisher's duration, codec, slot, or composition constraints.

See [Creative representation sets](/dist/docs/3.2.0-beta.8/creative/representation-sets), [CTV](/dist/docs/3.2.0-beta.8/creative/channels/ctv), [Canonical formats](/dist/docs/3.2.0-beta.8/creative/canonical-formats), and [Creative manifests](/dist/docs/3.2.0-beta.8/creative/creative-manifests).
