> ## Documentation Index
> Fetch the complete documentation index at: https://agenticadvertisingorg-snap-format-preview-links.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# preview_creative

> preview_creative renders an existing creative manifest into viewable output in AdCP, in single or batch mode, returning URL, image, or HTML output.

`preview_creative` renders an existing creative manifest into viewable output. It does not generate or modify the input manifest — use [`build_creative`](/docs/creative/task-reference/build_creative) for that. Supports both single creative preview and batch preview (5-10x faster for multiple creatives).

**Request Schema**: [`/schemas/v3/creative/preview-creative-request.json`](https://adcontextprotocol.org/schemas/v3/creative/preview-creative-request.json)
**Response Schema**: [`/schemas/v3/creative/preview-creative-response.json`](https://adcontextprotocol.org/schemas/v3/creative/preview-creative-response.json)

## Quick Start

### Single Creative Preview

```json theme={null}
{
  "request_type": "single",
  "creative_manifest": { /* includes format_id, assets */ }
}
```

Response:

```json theme={null}
{
  "response_type": "single",
  "previews": [
    {
      "preview_id": "prev_001",
      "renders": [
        {
          "render_id": "render_1",
          "output_format": "url",
          "preview_url": "https://creative-agent.example.com/preview/abc123",
          "role": "primary"
        }
      ],
      "input": { "name": "Default", "macros": {} }
    }
  ],
  "expires_at": "2027-02-15T18:00:00Z"
}
```

Embed the primary render in an iframe:

```html theme={null}
<iframe src="https://creative-agent.example.com/preview/abc123"
        width="600" height="400"></iframe>
```

### Direct HTML Embedding

For faster rendering without iframe overhead, request HTML directly:

```json theme={null}
{
  "request_type": "single",
  "creative_manifest": { /* includes format_id, assets */ },
  "output_format": "html"
}
```

Response contains raw HTML:

```json theme={null}
{
  "response_type": "single",
  "previews": [
    {
      "preview_id": "prev_002",
      "renders": [
        {
          "render_id": "render_1",
          "output_format": "html",
          "preview_html": "<div class=\"creative\">...</div>",
          "role": "primary"
        }
      ],
      "input": { "name": "Default", "macros": {} }
    }
  ],
  "expires_at": "2027-02-15T18:00:00Z"
}
```

<Warning>
  Only use `output_format: "html"` with trusted creative agents. Direct HTML embedding bypasses iframe sandboxing.
</Warning>

### Batch Preview (Multiple Creatives)

Preview multiple creatives in one API call (5-10x faster):

```json theme={null}
{
  "request_type": "batch",
  "requests": [
    { "creative_manifest": { /* creative 1 */ } },
    { "creative_manifest": { /* creative 2 */ } }
  ]
}
```

Response contains results in order:

```json theme={null}
{
  "response_type": "batch",
  "results": [
    { "success": true, "creative_id": "creative_1", "response": { "previews": [...], "expires_at": "..." } },
    { "success": true, "creative_id": "creative_2", "response": { "previews": [...], "expires_at": "..." } }
  ]
}
```

### Variant Preview (Post-Flight)

Preview what a specific variant looked like when served. Use `variant_id` from `get_creative_delivery` response:

```json theme={null}
{
  "request_type": "variant",
  "variant_id": "gen_mobile_morning"
}
```

Response:

```json theme={null}
{
  "response_type": "variant",
  "variant_id": "gen_mobile_morning",
  "previews": [
    {
      "preview_id": "prev_gen_morning",
      "renders": [
        {
          "render_id": "render_1",
          "output_format": "url",
          "preview_url": "https://creative-agent.example.com/preview/variant/gen_mobile_morning",
          "role": "primary",
          "dimensions": { "width": 300, "height": 250 }
        }
      ]
    }
  ],
  "manifest": {
    "format_id": {
      "agent_url": "https://creative.example.com",
      "id": "display_300x250_generative"
    },
    "assets": {
      "hero_image": {
        "asset_type": "image",
        "url": "https://cdn.creative.example.com/generated/mobile_morning_v1.jpg",
        "width": 300,
        "height": 250
      },
      "headline": {
        "asset_type": "text",
        "content": "Start Your Summer Right"
      }
    }
  },
  "expires_at": "2027-02-15T18:00:00Z"
}
```

Since each variant from `get_creative_delivery` includes its full `manifest`, you can also pass the manifest directly to `preview_creative` as a standard single request to re-render it.

## Request Parameters

All modes use a single flat object with `request_type` as the discriminant.

| Parameter           | Type     | Required | Description                                                                                                                                                           |
| ------------------- | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `request_type`      | string   | Yes      | `"single"`, `"batch"`, or `"variant"`                                                                                                                                 |
| `creative_manifest` | object   | Single   | Complete creative manifest with all required assets for the format.                                                                                                   |
| `format_id`         | FormatID | No       | Format identifier (agent\_url + id). Defaults to `creative_manifest.format_id` if omitted. Used in single mode.                                                       |
| `inputs`            | array    | No       | Array of input sets for multiple preview variants. Used in single mode.                                                                                               |
| `quality`           | string   | No       | `"draft"` (fast, lower-fidelity) or `"production"` (full quality). In batch mode, sets the default for all requests.                                                  |
| `output_format`     | string   | No       | `"url"` (default) or `"html"`. In batch mode, sets the default for all requests.                                                                                      |
| `item_limit`        | integer  | No       | Maximum catalog items to render per preview variant. Used in single mode.                                                                                             |
| `template_id`       | string   | No       | Specific template ID for custom format rendering. Used in single mode.                                                                                                |
| `requests`          | array    | Batch    | Array of 1-50 preview requests. Each item accepts `creative_manifest` (required), `format_id`, `inputs`, `quality`, `output_format`, `item_limit`, and `template_id`. |
| `variant_id`        | string   | Variant  | Platform-assigned variant identifier from `get_creative_delivery`.                                                                                                    |
| `creative_id`       | string   | No       | Creative identifier for context. Used in variant mode.                                                                                                                |

**Required** column values: *Single* = required when `request_type` is `"single"`, *Batch* = required when `"batch"`, *Variant* = required when `"variant"`.

### Input Sets

Generate multiple preview variants by providing different contexts:

```json theme={null}
{
  "inputs": [
    { "name": "Desktop", "macros": { "DEVICE_TYPE": "desktop" } },
    { "name": "Mobile", "macros": { "DEVICE_TYPE": "mobile" } },
    { "name": "Morning Context", "context_description": "User commuting to work" }
  ]
}
```

**Available macros**: `DEVICE_TYPE`, `COUNTRY`, `CITY`, `DMA`, `GDPR`, `US_PRIVACY`, `CONTENT_GENRE`, etc.

**Context descriptions**: For AI-generated content like host-read audio ads.

## Response Format

### Single Mode Response

```typescript theme={null}
{
  response_type: "single";
  previews: Preview[];       // One per input (or one default)
  interactive_url?: string;  // Optional sandbox for interactive formats
  expires_at?: string;       // Optional ISO 8601 expiration; omitted means no expiration
}
```

### Batch Mode Response

```typescript theme={null}
{
  response_type: "batch";
  results: Array<{
    success: boolean;
    creative_id: string;
    response?: { previews: Preview[]; expires_at?: string; };
    errors?: Array<{ code: string; message: string; }>;
  }>;
}
```

### Preview Structure

```typescript theme={null}
{
  preview_id: string;
  renders: Array<{
    render_id: string;
    output_format: "url" | "html" | "both";
    preview_url?: string;     // When output_format is "url" or "both"
    preview_html?: string;    // When output_format is "html" or "both"
    role: string;             // "primary", "companion", etc.
    dimensions?: { width: number; height: number; };
  }>;
  input: {
    name: string;
    macros?: Record<string, string>;
    context_description?: string;
  };
}
```

**Multi-render formats**: Some formats produce multiple pieces (video + companion banner). Each has its own `render_id` and `role`.

## Previewing generative creative

For generative formats — contextual display, AI-generated native, conversational ads — the creative doesn't exist until serve time. Preview serves two distinct purposes:

### Pre-flight: representative samples

Before the campaign runs, use single or batch mode to preview what the agent *could* generate given different contexts. Pass `inputs` with `context_description` to simulate serve-time conditions:

```json theme={null}
{
  "$schema": "/schemas/creative/preview-creative-request.json",
  "request_type": "single",
  "quality": "draft",
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://ads.seller-example.com",
      "id": "contextual_display_generative"
    },
    "assets": {
      "brief": {
        "asset_type": "brief",
        "name": "Sustainability story",
        "objective": "awareness",
        "messaging": {
          "key_messages": ["Highlight our sustainability story. Match tone to editorial context."]
        }
      }
    }
  },
  "inputs": [
    { "name": "Tech article", "context_description": "Article about semiconductor manufacturing" },
    { "name": "Lifestyle blog", "context_description": "Blog post about sustainable living" }
  ]
}
```

These previews are *representative*, not definitive. Real serve-time output depends on live signals (actual page content, user device, time of day) that can't be fully simulated. Use draft quality for fast iteration on the brief and creative direction, then production quality for stakeholder review.

### Post-flight: exact replay

After the campaign runs, use variant mode to see exactly what was served. Pass a `variant_id` from `get_creative_delivery`:

```json theme={null}
{
  "request_type": "variant",
  "variant_id": "gen_tech_mobile_001"
}
```

The response includes the variant's actual manifest — the specific headline, image, and layout the agent generated for that context. This is a faithful replay, not a re-generation.

### Setting expectations

| Aspect                  | Standard creative                      | Generative creative                                                                       |
| ----------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------- |
| Pre-flight preview      | Exact — what you see is what runs      | Representative — shows the agent's interpretation of the brief under simulated conditions |
| Post-flight preview     | Same as pre-flight                     | Exact — faithful replay of served output via variant mode                                 |
| `quality: "draft"`      | Fast wireframe-quality render          | Fast, lower-fidelity generation for reviewing creative direction                          |
| `quality: "production"` | Full-fidelity render                   | Full-quality generation for stakeholder sign-off                                          |
| Number of variants      | Typically 1 (or a few device variants) | Potentially thousands — one per context                                                   |

For generative formats where every impression produces a different creative (like AI chat or real-time contextual), pre-flight previews are best understood as *samples from a distribution* rather than *the ad*. The brief and brand identity constrain the distribution; previews let you verify the agent interprets those constraints correctly.

### Conversational and interactive formats

For formats where the ad is stateful — AI chat, interactive experiences, conversational native — preview takes on additional meaning:

* **Pre-flight** renders a representative first interaction or simulated conversation. The `interactive_url` field in the preview response (when present) provides a sandbox where reviewers can interact with the experience directly. Use `context_description` to simulate different conversation entry points.
* **Post-flight** variant replay shows the actual exchange that occurred. For multi-turn formats, the variant manifest captures the full content the agent produced (message sequence, responses, media assets shown). The level of detail depends on the agent — some provide full transcripts, others provide summarized content with anonymized user signals.

These formats have the widest gap between pre-flight and post-flight: a pre-flight preview can only approximate one possible conversation path, while the live experience adapts to each user. Preview enough scenarios to verify tone, guardrails, and brand consistency.

### Quality mismatch

If the requested quality level is not supported, the agent renders at the best quality it can provide. The protocol does not require agents to support both levels — an agent that only generates at one fidelity ignores the parameter. There is no response field echoing back the actual quality used, so if quality accuracy matters for your workflow, verify by visual inspection or ask the agent about its capabilities through `list_creative_formats`.

### Preview expiration and variant retention

Preview responses may include an `expires_at` timestamp. When present, consumers should treat preview URLs as invalid after that time and re-generate them before reuse. When `expires_at` is omitted, the preview URLs do not expire. For generative creative, re-generating a pre-flight preview may produce different output — the same brief and context can yield different creative each time.

### Preview URL durability

`preview_url` is the protocol resource buyers and MCPUI hosts render. AdCP does not define a separate durable asset pointer for preview renders in 3.x; if a creative agent needs an internal asset key, resource URI, or storage object ID, it remains agent-internal unless the schema adds a future field for it.

Creative agents MUST keep each `preview_url` dereferenceable until the response's `expires_at` timestamp. When `expires_at` is omitted, the URL has no protocol-level expiration and must remain dereferenceable until the agent explicitly revokes or purges it out of band. Do not back preview URLs only with pod-local `Map`/LRU state in multi-process or multi-pod deployments, because a browser fetch, later refinement call, or reviewer session may land on a different process than the one that created the preview.

Durable storage does not require permanent public CDN hosting. A preview URL can resolve through the creative agent's authenticated preview route as long as the route can recover the render from shared storage, such as a database row, object store key, or shared cache tier, for the advertised lifetime.

Variant previews (post-flight) depend on the agent retaining variant data. Agents are not required to retain variant data indefinitely. If you request a variant preview for a variant the agent has purged, expect a standard error response. For long-running campaigns, retrieve and archive variant previews periodically rather than assuming they will remain available.

## Examples

### Device Variants

```json theme={null}
{
  "$schema": "/schemas/creative/preview-creative-request.json",
  "request_type": "single",
  "creative_manifest": {
    "format_id": { "agent_url": "https://creative.adcontextprotocol.org", "id": "native_responsive" },
    "assets": {
      "hero_image": { "asset_type": "image", "url": "https://cdn.example.com/hero.jpg", "width": 1200, "height": 627 },
      "headline": { "asset_type": "text", "content": "Veterinarian Recommended" }
    }
  },
  "inputs": [
    { "name": "Desktop", "macros": { "DEVICE_TYPE": "desktop" } },
    { "name": "Mobile", "macros": { "DEVICE_TYPE": "mobile" } }
  ]
}
```

### Batch with HTML Output

Preview multiple creatives for a grid layout:

```json theme={null}
{
  "request_type": "batch",
  "output_format": "html",
  "requests": [
    { "creative_manifest": { /* creative 1 */ } },
    { "creative_manifest": { /* creative 2 */ } }
  ]
}
```

### AI-Generated Audio Preview

```json theme={null}
{
  "$schema": "/schemas/creative/preview-creative-request.json",
  "request_type": "single",
  "creative_manifest": {
    "format_id": { "agent_url": "https://creative.adcontextprotocol.org", "id": "audio_host_read_30s" },
    "assets": {
      "script_template": { "content": "This episode brought to you by {{BRAND_NAME}}..." },
      "brand_voice": { "content": "Friendly, enthusiastic, conversational." }
    }
  },
  "inputs": [
    { "name": "Weather Podcast", "context_description": "Podcast discussing weather patterns" },
    { "name": "Fitness Podcast", "context_description": "Podcast about marathon training" }
  ]
}
```

## HTTP Status Codes

**Single mode:**

* **200 OK** - Preview generated successfully
* **400 Bad Request** - Invalid manifest or format\_id
* **404 Not Found** - Format not supported

**Batch mode:**

* **200 OK** - Batch processed (check individual `success` fields)
* **400 Bad Request** - Invalid batch structure

## Key Points

* Every render's `preview_url` returns an HTML page for iframe embedding
* Use `output_format: "html"` for grids of 10+ previews (no iframe overhead)
* Batch mode is 5-10x faster than individual requests
* Preview URLs expire only when `expires_at` is present; omitted `expires_at` means no protocol-level expiration
* Back preview URLs with storage that survives the URL's advertised lifetime; process-local maps are only appropriate for single-process demos or shorter-than-process-lifetime URLs
* Handle partial batch failures by checking each result's `success` field

## Related Documentation

* [Advanced Preview Patterns](/docs/creative/task-reference/preview_creative-advanced) - Caching, workflows, implementation notes
* [Creative Manifests](/docs/creative/creative-manifests) - Manifest structure
* [Creative Formats](/docs/creative/formats) - Format specifications
