> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.videogen.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.videogen.io/_mcp/server.

# File hydration

> How file hydration works in the VideoGen API: call POST /v1/files/{id}/hydrate to get fresh signed URLs for thumbnails, previews, and downloads, or use the getHydratedFile SDK helper.

Files returned by the VideoGen API include signed URLs for downloading thumbnails, previews, and the full-resolution asset. These URLs expire after a period of time. Hydration generates fresh URLs so you can access the file again.

Hydration: `POST /v1/files/{fileId}/hydrate` returns a full `FileInfo` with fresh `thumbnailSource`, `previewSource`, `downloadSource`, and `hlsSource` URLs. The `getHydratedFile` SDK helper calls `getFile` first and only hydrates when URLs are missing or expired.

## When to hydrate

File source URLs are time-limited. You need to hydrate a file when:

* The `downloadSource`, `previewSource`, or `thumbnailSource` is `null`
* A source has `status: "pending"` (still processing)
* A source URL has passed its `expiresAt` timestamp
* You stored a `fileId` and need to access the file later

Webhook payloads and freshly completed tool executions include hydrated URLs already, so you typically only need to hydrate when accessing files some time after they were created.

## Hydrate with the SDK

The `getHydratedFile` helper checks whether URLs are still valid and only calls the hydrate endpoint when necessary:

#### TypeScript

```typescript
import { VideoGen, getHydratedFile } from "@videogen/sdk";

const client = new VideoGen({ apiKey: "sk_videogen_live_..." });

const file = await getHydratedFile({ client, fileId: "vg_file_..." });

console.log(file.downloadSource?.url);   // fresh signed URL
console.log(file.thumbnailSource?.url);  // fresh signed URL
console.log(file.previewSource?.url);    // fresh signed URL
```

#### cURL

```bash
curl -X POST https://api.videogen.io/v1/files/vg_file_.../hydrate \
  -H "Authorization: Bearer sk_videogen_live_..."
```

## Response

The hydrate endpoint returns the full `FileInfo` object with populated source URLs:

```json
{
  "fileId": "vg_file_...",
  "type": "IMAGE",
  "scope": "GLOBAL",
  "displayName": "A mountain at sunrise",
  "thumbnailSource": {
    "status": "ready",
    "url": "https://...",
    "expiresAt": 1745413200,
    "width": 256,
    "height": 256
  },
  "previewSource": {
    "status": "ready",
    "url": "https://...",
    "expiresAt": 1745413200,
    "width": 720,
    "height": 720
  },
  "downloadSource": {
    "status": "ready",
    "url": "https://...",
    "expiresAt": 1745413200,
    "width": 1024,
    "height": 1024
  }
}
```

Each source includes:

| Field       | Type                                                  | Description                                            |
| ----------- | ----------------------------------------------------- | ------------------------------------------------------ |
| `status`    | `"pending"` \| `"ready"` \| `"failed"` \| `"skipped"` | Processing status of this rendition.                   |
| `url`       | `string \| null`                                      | Signed download URL. Present when status is `"ready"`. |
| `expiresAt` | `number \| null`                                      | URL expiration as seconds since the Unix epoch (UTC).  |
| `width`     | `integer \| null`                                     | Width in pixels (images and video only).               |
| `height`    | `integer \| null`                                     | Height in pixels (images and video only).              |
| `fileBytes` | `integer \| null`                                     | File size in bytes, when available.                    |

## Downloading files

The `downloadFile` helper combines hydration and download into a single call:

#### TypeScript

```typescript
import { VideoGen, downloadFile } from "@videogen/sdk";

const client = new VideoGen({ apiKey: "sk_videogen_live_..." });

// Stream to disk
await downloadFile({
  client,
  fileId: "vg_file_...",
  outputPath: "./mountain.png",
});

// Or get the raw response
const response = await downloadFile({ client, fileId: "vg_file_..." });
const bytes = await response?.arrayBuffer();
```

#### cURL

```bash
# 1. Hydrate to get a fresh URL
curl -X POST https://api.videogen.io/v1/files/vg_file_.../hydrate \
  -H "Authorization: Bearer sk_videogen_live_..."

# 2. Download from the returned URL
curl -o mountain.png "<downloadSource.url>"
```

## Source statuses

| Status    | Meaning                                                            |
| --------- | ------------------------------------------------------------------ |
| `pending` | The rendition is still being processed. Hydrate again shortly.     |
| `ready`   | The rendition is available and the URL is valid until `expiresAt`. |
| `failed`  | Processing failed for this rendition.                              |
| `skipped` | This rendition doesn't apply (e.g. thumbnails for audio files).    |