Issue: simplify PreviewCreativeResponse for the single-render case
Type: schema ergonomics / nesting depth
Severity: medium (every creative-template adopter hits this on day 1)
Target: 3.x minor (additive — keep the union, hoist common fields)
Problem
PreviewCreativeResponse is a 3-variant discriminated union by response_type (single | batch | variant) where the single variant — the common case for stateless creative-template platforms — requires four levels of nesting to surface a single preview URL:
{
response_type: 'single',
previews: [
{
preview_id: 'pv_1',
input: { name: 'default' }, // echo-back boilerplate
renders: [
{
render_id: 'r1',
output_format: 'url', // discriminator
role: 'primary', // semantic role for multi-piece
preview_url: 'https://...',
},
],
},
],
expires_at: '...',
}
For a watermarking platform, TTS service, or any single-output creative-template, the four nesting levels exist for shapes the platform doesn't use (preview-variants, multi-piece renders, macro echo-back). Adopters write the boilerplate or guess wrong.
Empirical: a controlled "be Emma" test of an AudioStack adapter against the v6.0 @adcp/client SDK + skill produced this verbatim feedback:
The skill's example returns { preview_url, expires_at } directly, but the generated PreviewCreativeResponse is a response_type-discriminated union with previews: [{ preview_id, renders: [...], input }]. I followed the generated shape; if the skill is intentionally lossy here it should be updated.
The adopter's instinct ({ preview_url, expires_at }) matched the actual common case; the wire shape forced the boilerplate.
Proposal
Two paths, in order of preference:
A. Hoist preview_url for single-render single-variant responses.
{
response_type: 'single',
preview_url: 'https://...', // when previews.length === 1 && renders.length === 1
expires_at: '...',
previews?: [...], // OPTIONAL — present for batch/variant only
}
The previews[] array remains the source of truth for batch/variant responses; for single-render-single-variant it becomes optional. Validators that find both preview_url and previews[] use preview_url as the canonical answer.
B. Add a preview_url shorthand at the response root regardless of variant.
For any response, if exactly one render exists, preview_url carries it. The full previews[] structure is still emitted for completeness and audit.
Backwards compatibility
- 3.x minor: emit
preview_url alongside previews[] when there's a single render. Existing consumers reading the nested shape are unaffected.
- 4.0: optional — promote
preview_url to "preferred" and demote previews[] to "advanced multi-render contract."
Files affected
schemas/v3/creative/preview-creative-response.json
docs/v3/creative/preview_creative.md
- llms.txt § preview_creative entry
Source
Surfaced during AdCP @adcp/client v6.0 SDK be-Emma test (audiostack-adapter test harness, round 2). The 4-level nesting is the most-cited DX friction point for stateless creative-template adopters.
Issue: simplify
PreviewCreativeResponsefor the single-render caseType: schema ergonomics / nesting depth
Severity: medium (every creative-template adopter hits this on day 1)
Target: 3.x minor (additive — keep the union, hoist common fields)
Problem
PreviewCreativeResponseis a 3-variant discriminated union byresponse_type(single | batch | variant) where thesinglevariant — the common case for stateless creative-template platforms — requires four levels of nesting to surface a single preview URL:For a watermarking platform, TTS service, or any single-output creative-template, the four nesting levels exist for shapes the platform doesn't use (preview-variants, multi-piece renders, macro echo-back). Adopters write the boilerplate or guess wrong.
Empirical: a controlled "be Emma" test of an AudioStack adapter against the v6.0
@adcp/clientSDK + skill produced this verbatim feedback:The adopter's instinct (
{ preview_url, expires_at }) matched the actual common case; the wire shape forced the boilerplate.Proposal
Two paths, in order of preference:
A. Hoist
preview_urlfor single-render single-variant responses.The
previews[]array remains the source of truth for batch/variant responses; for single-render-single-variant it becomes optional. Validators that find bothpreview_urlandpreviews[]usepreview_urlas the canonical answer.B. Add a
preview_urlshorthand at the response root regardless of variant.For any response, if exactly one render exists,
preview_urlcarries it. The fullpreviews[]structure is still emitted for completeness and audit.Backwards compatibility
preview_urlalongsidepreviews[]when there's a single render. Existing consumers reading the nested shape are unaffected.preview_urlto "preferred" and demotepreviews[]to "advanced multi-render contract."Files affected
schemas/v3/creative/preview-creative-response.jsondocs/v3/creative/preview_creative.mdSource
Surfaced during AdCP
@adcp/clientv6.0 SDK be-Emma test (audiostack-adapter test harness, round 2). The 4-level nesting is the most-cited DX friction point for stateless creative-template adopters.