# Preview a project

`GET https://api.vidmoat.com/v1/projects/{id}/preview`

- Scope: `render.read`
- Cost: Free

Metadata and layout lint (default), approximate composition HTML, or an exact rendered frame. For live playback with the app compositor, use the embedded player described in the video-preview guide.

> **Note.** format=json without `at` is cheap and starts no browser. A frame (format=image, or any request with `at`) launches Chromium and carries its own limit of 10 a minute per key, on top of your plan rate.

### Path parameters

- `id` (string, required): The project id.

### Query parameters

- `format` (enum, optional, default `json`): `json` for metadata and lint (plus a frame as a data URI when `at` is set), `image` for JPEG bytes, `html` for the composition. One of `json`, `image`, `html`.
- `at` (number, optional): Timeline time in seconds. Past the end is clamped. Defaults to 0 for `image`.
- `resolution` (enum, optional, default `full`): For `html` only. One of `full`, `half`.

## Response

Returns `200` (application/json, image/jpeg or text/html).

### Response fields

- `projectId` (string): The project.
- `durationSec` (number): Timeline length.
- `canvas` (object): `{ width, height, fps }`.
- `composition` (object): `{ url, contentType, timelineHandle, seekExample }`: the HTML composition and how to seek it.
- `frame` (object): Without `at`: `{ url, imageUrl, note }`. With `at`: `{ at, url, dataUri, width, height }`.
- `lint` (array): Layout warnings: `{ severity: "warn" | "note", time, message }`.
- `suggestedPreviewTimes` (array of numbers): Timestamps worth looking at with the preview endpoint before you render.

## Errors

Besides the errors any request can get ([authentication](https://developer.vidmoat.com/developer/docs/authentication#when-a-request-is-refused), [rate limits](https://developer.vidmoat.com/developer/docs/rate-limits)):

| Status | Code | When |
| --- | --- | --- |
| 404 | [`not_found`](https://developer.vidmoat.com/developer/docs/errors#not_found) | No such project, or it is not yours. The two are indistinguishable on purpose. |
| 400 | [`invalid_request`](https://developer.vidmoat.com/developer/docs/errors#invalid_request) | A frame was asked for but the project has no clips, or `at` is negative. |
| 429 | [`rate_limited`](https://developer.vidmoat.com/developer/docs/errors#rate_limited) | More than 10 frames a minute on this key. `retryAfterSec` says how long to wait. |
| 502 | [`provider_error`](https://developer.vidmoat.com/developer/docs/errors#provider_error) | The frame failed to render. |

## Request examples

```bash curl
curl "https://api.vidmoat.com/v1/projects/$ID/preview" \
  -H "Authorization: Bearer $VIDMOAT_KEY"

# a real frame, as JPEG bytes
curl "https://api.vidmoat.com/v1/projects/$ID/preview?format=image&at=2.5" \
  -H "Authorization: Bearer $VIDMOAT_KEY" -o frame.jpg
```

```js Node
const ID = 'YOUR_PROJECT_ID';

const res = await fetch(`https://api.vidmoat.com/v1/projects/${ID}/preview`, {
  headers: {
    Authorization: `Bearer ${process.env.VIDMOAT_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(data.error?.message ?? `HTTP ${res.status}`);
console.log(data);
```

```python Python
import os
import requests

ID = "YOUR_PROJECT_ID"

res = requests.get(
    f"https://api.vidmoat.com/v1/projects/{ID}/preview",
    headers={"Authorization": f"Bearer {os.environ['VIDMOAT_KEY']}"},
    timeout=60,
)
res.raise_for_status()
print(res.json())
```

## Example response

```json
{
  "projectId": "cm1abc",
  "durationSec": 12.5,
  "canvas": { "width": 1080, "height": 1920, "fps": 30 },
  "clipCount": 4,
  "composition": {
    "url": "https://api.vidmoat.com/api/v1/projects/cm1abc/preview?format=html",
    "contentType": "text/html",
    "timelineHandle": "window.__timelines.main",
    "seekExample": "window.__timelines.main.seek(2.5)"
  },
  "frame": {
    "url": "https://api.vidmoat.com/api/v1/projects/cm1abc/preview?at=<seconds>",
    "imageUrl": "https://api.vidmoat.com/api/v1/projects/cm1abc/preview?format=image&at=<seconds>",
    "note": "…"
  },
  "lint": [{ "severity": "warn", "time": 2, "message": "…" }],
  "suggestedPreviewTimes": [2]
}
```

---

Source: https://developer.vidmoat.com/developer/docs/api/renders/get-preview
Previous: [Get a render](https://developer.vidmoat.com/developer/docs/api/renders/get-render.md)
Next: [List media](https://developer.vidmoat.com/developer/docs/api/media/list-media.md)
All documentation: https://developer.vidmoat.com/llms-full.txt
