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

# Preview a review

> Resolve the safest available preview for one exact creative review placement

`POST /api/v2/storefront/creative-reviews/{creativeId}/preview`

Requests a preview for one exact package and placement context returned on the
creative review row. The context is opaque: the server revalidates the review
version, delivery route, provider, capability, package, and placement rather
than accepting those identities from the caller.

## Request

```bash theme={null}
curl -X POST \
  "https://api.interchange.io/api/v2/storefront/creative-reviews/review%3A42/preview" \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "context_ref": "75c90dd1-2430-4f2e-9bd0-c029f91ad5f7",
    "expected_content_digest": "0db36cf6c4bfb43123aee1c3eaf5ee965e1c34c9df606b02a56c72a226ad097a",
    "expected_review_version_digest": "4fde1cc1468051f05492bd3694348ea7f6dbb37bbbe5ff35967c4d4d149d9a4e"
  }'
```

## Parameters

| Field                            | Type   | Required | Notes                                                                                                                                                                                                                                          |
| -------------------------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `creativeId`                     | string | Yes      | Path param — use the `reviewRef` returned by the queue                                                                                                                                                                                         |
| `context_ref`                    | UUID   | Yes      | Opaque `previewContexts[].contextRef` from this exact review row                                                                                                                                                                               |
| `expected_content_digest`        | string | Yes      | The row's current 64-character SHA-256 `contentDigest`                                                                                                                                                                                         |
| `expected_review_version_digest` | string | No       | Send the row's `sourceTrust.reviewVersionDigest` when available. During a rolling upgrade, legacy callers may omit it; the server derives the current review identity and checks it under the dispatch lock and again after provider dispatch. |

## Response

```json theme={null}
{
  "status": "completed",
  "contextRef": "75c90dd1-2430-4f2e-9bd0-c029f91ad5f7",
  "authority": {
    "kind": "publisher_preview_provider",
    "authoritative": true,
    "fidelity": "authoritative",
    "placementId": "homepage-hero"
  },
  "preview": {
    "result": {
      "response_type": "single",
      "previews": ["opaque provider response retained for legacy callers"]
    },
    "expiresAt": "2026-09-02T00:05:00.000Z"
  },
  "representativeSellerPreview": {
    "result": { "response_type": "single" },
    "expiresAt": "2026-09-02T00:05:00.000Z"
  },
  "externalOpen": {
    "url": "https://preview.publisher.example/render/1",
    "hostname": "preview.publisher.example",
    "expiresAt": "2026-09-02T00:05:00.000Z",
    "authorizedOrigin": "https://preview.publisher.example"
  }
}
```

The explicit preview action (labelled `Preview on <provider domain>`, or
**Preview on placement** for a seller route) sends the exact manifest to the
authorized provider, where code or network activity may occur. Existing V2
callers continue to receive `preview.result` and, when present, the
`representativeSellerPreview` response as opaque inert data. Interchange never
executes, mounts, iframes, `srcdoc`s, or prefetches either payload. A separate
validated `externalOpen` envelope is offered only after a second explicit
**View provider preview** gesture through the standard MCP host `openLink`
bridge. The widget never renders an anchor or navigates directly.

Every `status: "completed"` response, including an optional
`representativeSellerPreview`, carries the exact valid expiry supplied by the
authorized provider. If the provider expiry is missing, invalid, or already
expired, its opaque payload remains inert and has no `externalOpen`; it cannot
be opened. The widget repeats URL, origin, and expiry validation immediately
before calling the host bridge.

This capability is generally available. The deployment kill switch can disable
interactive preview during an operational incident; when disabled, the server
issues interactive-preview availability as false, so the widget hides the
request action while leaving source inspection and approval available.

If no authorized render is available, the endpoint returns
`status: "source_only"`. Its authority is placement-specific metadata, while
submitted `display_tag` code and remote VAST are not executed to invent a
screenshot. Treat every returned URL or HTML render as untrusted. The separate
server-owned artifact renderer remains required for an inline rendered preview;
the MCP app does not substitute an iframe.

## Errors

* `400 VALIDATION_ERROR` — the review reference or either version digest is malformed.
* `404 NOT_FOUND` — the review context does not exist, is stale, belongs to a
  different storefront, or no longer matches the requested content digest.

See [Errors](/v2/reference/errors) for the full error contract.

## Related

<CardGroup cols={2}>
  <Card title="Get a review" href="/v2/storefront/creative-reviews/tasks/get-review" icon="magnifying-glass">
    Fetch the review and its current preview contexts
  </Card>

  <Card title="Decide a review" href="/v2/storefront/creative-reviews/tasks/decide-review" icon="gavel">
    Approve or reject after inspection
  </Card>
</CardGroup>
