A signed AdCP v3.2.3 create_media_buy can succeed while the VAST duration is wrong
AdCP v3.2.3 (Oct 7) enforces request signing on create_media_buy but does not compare VAST Duration to duration_ms, a dev.to post says. A signed, schema-valid buy can complete with the wrong creative behind the URL.
The Engineer · Build desk

Three figures from the post's example mismatch: the SDK schedules sixty-five seconds; the manifest's duration_ms is 30000, which satisfies a 60-second format capability bound.
| Figure | Value | Note | Claim |
|---|---|---|---|
| SDK schedules, in the post's example mismatch | 65 seconds | 2 | |
| Manifest duration_ms | 30,000 ms | 1 | |
| Capability bound | 60 seconds | 6 |
What happened
- A successful create_media_buy means the seller accepted the terms, returned a manifest and echoed the negotiated adcp_version.
- For video, the manifest's VAST asset can be a URL, so the XML itself was never part of the MCP payload.
- Since AdCP 3.1, format capabilities can declare duration_ms_range or duration_ms_exact, so buyers pick slots with explicit bounds.
- The CTV player, the SSAI stitcher and the verification SDK read XML and follow wrapper hops until they find an InLine.
Why it matters
- exposure The failure surfaces at playback and in measurement, after the buy returned success: the SDK schedules the longer spot, quartiles fire on the wrong clock, and some stacks reject the break.
- decision Teams running buyer or seller agents need their own step that follows the wrapper chain to the InLine and compares its Duration to duration_ms, because signing does not supply one.
- constraint A green conformance run shows the server speaks the protocol. It cannot gate creative readiness.
The duration_ms field in the manifest is optional. The schema marks it with the note "if known" [11]. Since nothing fetches the tag [8], the value, when present, is a claim. The post cites a companion write-up on declared versus verified assets that says as much: "every field on the VAST asset is a claim about a document nobody parsed during the buy" [4].
Wrappers widen the gap. The manifest stores one URL, and hop one can be a Wrapper with no Duration, because duration sits on the terminal InLine [15]. QA that stops at the first response has approved a redirect graph, the post says. Identity fields drift the same way. The JSON may reference a creative id while the tag omits UniversalAdId or ships a registry value the SSAI path cannot resolve [16].
The post's numbers show how each layer can pass on its own. A 30,000 ms manifest sits inside a 60-second capability bound, and the InLine reads 00:01:05 [1]. That is 65 seconds. It is 35 seconds longer than the manifest [5] and 5 seconds over the bound [6]. The example is constructed. The post does not report a live incident.
We think leaving the fetch out of the signed call is a defensible boundary. A tool that downloaded and parsed a wrapper chain would put third-party ad servers inside the latency of a spend commitment. The cost moves elsewhere: someone has to open the XML before the flight starts.
The post's remedy is a linter. It names vastlint, which it says owns the creative envelope the video buy referenced [3]. All of this rests on that one dev.to post.
What to watch
- Whether AdCP adds a duration cross-check, or a rule that sellers resolve the tag, to the spec or the conformance storyboards.
- Whether duration_ms moves from optional to required on the VAST asset, or sellers start populating it by default.
- A reported case of a signed buy serving a duration different from its manifest.
Clarity's read
What the record supports and how the coverage leans. The claims behind it follow.
Reality
- Evidence35
- Adoption
- Insufficient
- Hype gap+10
- Incentives60
- Confidence50
Claim ledger
Ranked by verification strength, evidence, and original report placement.
- [1]
In the post's example mismatch, a manifest duration_ms of 30000 satisfies a sixty-second format capability bound, while the InLine's <Duration> reads 00:01:05, sixty-five seconds.
- [2]
In that example the SDK schedules sixty-five seconds, quartile tracking fires on the wrong clock, and some stacks reject the break outright.
- [3]
The post says vastlint owns the creative envelope the video buy referenced.
- [4]
A companion 'declared versus verified asset' post states that every field on the VAST asset is a claim about a document nobody parsed during the buy.
- [5]
The example InLine duration exceeds the manifest duration by 35 seconds.
- [6]
The example InLine duration exceeds the 60-second capability bound by 5 seconds.
- [7]
On October 7, 2026 AdCP shipped v3.2.3 with a security fix that enforces request signing on spend-committing calls such as create_media_buy.
- [8]
The v3.2.3 fix does not fetch the tag behind a VAST asset URL or compare <Duration> to the duration_ms in the manifest.
- [9]
A buy can be signed, schema-valid, and complete while the InLine the stitcher needs is still wrong.
- [10]
A buyer agent discovers inventory with get_products, checks get_adcp_capabilities, and commits with create_media_buy; success means the seller accepted the terms, returned a manifest, and echoed the negotiated adcp_version.
- [11]
The AdCP schema marks duration_ms on the VAST asset as optional ('if known').
- [12]
With delivery_type: url on a VAST asset, the VAST bytes were not part of the MCP payload.
- [13]
Format capabilities from AdCP 3.1 can declare duration_ms_range or duration_ms_exact so buyers select slots with explicit bounds.
- [14]
The CTV player, the SSAI stitcher and the verification SDK read XML and follow wrapper hops until they find an InLine or fail.
- [15]
The manifest stores one URL; hop one can be a <Wrapper> with no <Duration>, and duration lives on the terminal InLine. QA that stops at the first response approves a redirect graph, not a servable creative.
- [16]
AdCP may reference a creative id in JSON while the tag omits UniversalAdId or ships a registry value the SSAI path cannot resolve.
- [17]
AdCP conformance storyboards grade whether a server speaks the protocol: auth headers, idempotency, schema on each response, and on 3.2.x signatures where the trust model requires them; passing is not a substitute for opening the tag.
Get this ledger inside ChatGPT. Ask about any of our stories and the answer brings its figure, each claim’s verdict and the sources. Free, no account.
Sources
1 independent publisher whose own reporting we read for this story.
- dev.toAdCP Video Buy vs VAST InLine: The MCP Task Can Finish Before the Player Has a Spot
1 article · October 13, 2026
Topics and entities
Follow any of these and your For You feed starts watching them — no settings page required.
Topics
- VAST video ad servingFollow
- Model Context ProtocolFollow
- Agentic ad buyingFollow
- Connected TV advertisingFollow