> 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.

# Get project export

GET https://api.videogen.io/v1/projects/{projectId}/exports/{exportId}

Returns the current status of a project export started via `POST /v1/projects/{projectId}/export`, and — once `status` is `succeeded` — the signed download/thumbnail URLs and the hydrated export `file`. Poll this endpoint until `status` is `succeeded`, `failed`, or `cancelled`. The signed URLs are private and valid for 7 days; this endpoint automatically re-signs them when they are within an hour of expiring, so a caller always receives a URL valid long enough to use. Every endpoint that returns hydrated files auto-rehydrates this way — only the file endpoints (`GET /v1/files/{fileId}` and `POST /v1/files/{fileId}/hydrate`) are the explicit, on-demand hydration paths. Use `exportFileId` with `POST /v1/files/{fileId}/hydrate` if you need to re-sign the export file directly later.

Reference: https://docs.videogen.io/rest-api-reference/projects/get-project-export

## Authentication

- `Authorization` header (bearer token, required) — API key from [app.videogen.io/api](https://app.videogen.io/api). The full key is only shown once when you create it.

## Request

### Path parameters

- `projectId` (string, required) — The project id (e.g. `vg_proj_...`).
- `exportId` (string, required) — The export id (e.g. `vg_expo_...`) returned by `POST /v1/projects/{projectId}/export`.

## Response

### 200

Export status.

- `exportId` (string, required) — Opaque export id (e.g. `vg_expo_...`) matching the original request.
- `projectId` (string, required) — Id of the exported project (e.g. `vg_proj_...`).
- `status` (enum, required) — Lifecycle status shared by every asynchronous job (tool executions, workflow runs, remix actions, project exports, and timeline interchange jobs). `pending` and `running` are in-progress; `succeeded`, `failed`, and `cancelled` are terminal.
  - Allowed values: `pending`, `running`, `succeeded`, `failed`, `cancelled`
- `progressPercentage` (double, required) — Completion progress for the current attempt (0-100). Always `100` when `status` is `succeeded`.
- `attemptIndex` (integer, required) — Zero-based index of the current or most recent export attempt.
- `downloadUrl` (string, required, nullable) — Private signed MP4 download URL, valid for 7 days from when it was signed. Always present as a field; `null` until `status` is `succeeded`. This endpoint automatically re-signs the URL when it is within an hour of expiring, so a fresh call to get the export always returns a URL valid long enough to use. See `downloadUrlExpiresAt` for the exact expiry. To fetch a fresh URL directly from the underlying file at any time, use `exportFileId` with the hydrate-file endpoint.
- `downloadUrlExpiresAt` (integer, required, nullable) — Seconds since epoch (Unix timestamp) when `downloadUrl` expires. `null` while `downloadUrl` is null.
- `thumbnailUrl` (string, required, nullable) — Private signed thumbnail URL, valid for 7 days from when it was signed. Always present as a field; `null` until `status` is `succeeded` (and when no thumbnail is available). Re-signed automatically on the same terms as `downloadUrl`.
- `thumbnailUrlExpiresAt` (integer, required, nullable) — Seconds since epoch (Unix timestamp) when `thumbnailUrl` expires. `null` while `thumbnailUrl` is null.
- `exportFileId` (string, required, nullable) — File id (e.g. `vg_file_...`) of the exported MP4. Always present as a field; `null` until `status` is `succeeded`. Pass it to `POST /v1/files/{fileId}/hydrate` to fetch fresh signed URLs directly from the file at any time, which is useful once the 24-hour URLs above have expired.
- `file` (FileInfo, required, nullable) — Hydrated export file metadata with signed download URLs. Always present as a field; `null` until `status` is `succeeded`. Its signed URLs follow the same 24-hour validity and automatic re-signing as `downloadUrl`.
- `error` (ApiError, required, nullable) — Error details. Always present as a field; `null` unless `status` is `failed`.

## Types

### FileInfo

Metadata for a generated file. Obtain ids from tool results or `GET /v1/files`.

- `fileId` (string, required) — File id (e.g. `vg_file_...`).
- `scope` (enum, required) — File scope. - `GLOBAL`: user-uploaded or standalone generated files that persist indefinitely. - `PROJECT`: project-specific files (e.g. text-to-speech clips in a generated project). - `EXPORT`: project exports. - `TEMPORARY`: short-lived files guaranteed to be available for 24 hours, after which they may be archived at any time. Not analyzed (no description, transcript, or embedding). - `ENTITY`: files attached to a reusable entity (e.g. a voice sample for an actor), shared across your team.
  - Allowed values: `GLOBAL`, `PROJECT`, `EXPORT`, `TEMPORARY`, `ENTITY`
- `type` (enum, optional, nullable) — File type. Null when the file is still being processed and the type has not yet been determined.
  - Allowed values: `IMAGE`, `VIDEO`, `AUDIO`, `PDF`, `SLIDESHOW`, `TEXT`, `LOTTIE`
- `displayName` (string, optional) — Display name for the file.
- `description` (string, optional, nullable)
- `durationSeconds` (double, optional, nullable) — Duration in seconds for video and audio files. Null for images.
- `transcript` (Transcript, optional, nullable) — Timed transcript for video and audio files, when available, as a `Transcript` object with timed `words`. Null for images or when no transcript has been generated. For plain transcript text, use `transcriptText`.
- `transcriptText` (string, optional, nullable) — Plain transcript text for video and audio files, when available. Null for images or when no transcript has been generated.
- `downloadUrl` (string, optional, nullable) — Private signed URL for the highest-quality downloadable rendition, provided at the top level for convenience. Valid for 7 days from when it was signed. `null` when the rendition is still processing or the URL has not been signed yet. See `downloadUrlExpiresAt` for the exact expiry and `downloadSource` for the full rendition metadata; call `POST /v1/files/{fileId}/hydrate` to refresh it.
- `downloadUrlExpiresAt` (integer, optional, nullable) — Seconds since epoch (Unix timestamp) when `downloadUrl` expires. `null` when `downloadUrl` is null.
- `thumbnailUrl` (string, optional, nullable) — Private signed URL for the thumbnail rendition, provided at the top level for convenience. Valid for 7 days from when it was signed. `null` for file types that have no thumbnail (e.g. audio) or when it has not been signed yet. See `thumbnailSource` for the full rendition metadata.
- `thumbnailUrlExpiresAt` (integer, optional, nullable) — Seconds since epoch (Unix timestamp) when `thumbnailUrl` expires. `null` when `thumbnailUrl` is null.
- `thumbnailSource` (FileSource, optional, nullable) — Thumbnail image source. Populated after hydration.
- `previewSource` (FileSource, optional, nullable) — Preview rendition source (720p for video, resized for images). Populated after hydration.
- `downloadSource` (FileSource, optional, nullable) — Highest-quality downloadable rendition. Populated after hydration.
- `hlsSource` (FileSource, optional, nullable) — Private HLS streaming source. Populated for video and audio files once streaming renditions are ready. Uses a signed token; treat like other signed sources.
- `isPublicPreviewEnabled` (boolean, optional) — Whether public preview is enabled for this file. When true, `staticPublicPreviewSource` is populated for all file types. For video and audio, `publicHlsUrl` and `publicPlaybackId` are also populated once embed streaming is ready.
- `staticPublicPreviewSource` (FileSource, optional, nullable) — Permanent public URL for the file's highest-quality rendition. Populated when `isPublicPreviewEnabled` is true. Does not expire (`expiresAt` is null). Use for direct links to images, downloads, or any file type. For embedded video or audio players, prefer `publicPlaybackId`.
- `publicHlsUrl` (string, optional, nullable) — Public HLS streaming URL for video and audio. Only present when `isPublicPreviewEnabled` is true and embed streaming is ready. Prefer `publicPlaybackId` with `@videogen/player` for embeds.
- `publicPlaybackId` (string, optional, nullable) — Encoded public playback id (e.g. `vg_play_...`) for video and audio embeds. Pass this to `@videogen/player` or `@videogen/player-react`. Only present when `isPublicPreviewEnabled` is true and embed streaming is ready. For a permanent direct file URL (any type), use `staticPublicPreviewSource` instead.
- `sourceToolType` (string, optional) — Tool type that generated this file (e.g. `GENERATE_IMAGE`, `TEXT_TO_SPEECH`). Only present when the file was created by a tool execution.
- `sourceToolExecutionId` (string, optional) — Execution id of the tool call that generated this file (e.g. `vg_tool_...`). Only present when the file was created by a tool execution.
- `fileAnalysisMetadata` (FileAnalysisMetadata, optional) — Background analysis state for the file (used to populate `description`, `transcript`, `durationSeconds`, and the search embedding). Omitted when the file was returned via a path that does not check analysis progress (e.g. tool-result inline files and webhook payloads).

### ApiError

Standard error body returned with every non-2xx response (the `default` response of every operation). The HTTP status code conveys the error class; this body carries the details: - `400` invalid request, `401` missing or invalid API key, `403` not permitted (e.g. plan or add-on required, see `requirement`), `404` not found, `409` conflict, `429` rate limited or out of credits, `5xx` server error. Common `code` values include `invalid_request`, `invalid_api_key`, `not_authorized`, `not_found`, `insufficient_credits`, and `rate_limited`. Always branch on `code` (and `requirement.type` when present) rather than parsing `message`.

- `message` (string, required) — Human-readable error description. For display and logging only; do not branch on its exact text.
- `code` (string, optional, nullable) — Machine-readable error code in snake_case (e.g. `invalid_api_key`, `insufficient_credits`). `null` when no specific code applies.
- `requirement` (ErrorRequirement, optional, nullable) — What is needed to resolve the error. Present when the error can be fixed by fulfilling a specific requirement (e.g. purchasing an add-on); `null` otherwise.
- `internalErrorCode` (string, optional, nullable) — Opaque internal error code for debugging. Include this when contacting support. `null` when not applicable.

### Transcript

A transcript of an audio file, as timed words in order.

- `words` (list of TranscriptWord, required) — The transcript words, sorted by `startSeconds` and non-overlapping. Must contain at least one word.
- `languageCode` (string, optional, nullable) — Optional BCP-47 language code of the spoken audio (e.g. `en`, `es`). Used to tag the transcript's language; omit if unknown.

### FileSource

A rendition source for a file (e.g. thumbnail, preview, download). Contains a signed URL and metadata.

- `status` (enum, required) — `pending`: asset is still processing or has not been hydrated yet. `ready`: signed URL is available. `failed`: rendition generation failed. `skipped`: rendition does not apply to this file type (e.g. thumbnail for audio).
  - Allowed values: `pending`, `ready`, `failed`, `skipped`
- `url` (string, optional, nullable) — Signed URL. Present when status is `ready` and file has been recently hydrated. If missing, call the hydrate endpoint.
- `expiresAt` (integer, optional, nullable) — Seconds since epoch (Unix timestamp) when the signed URL expires.
- `width` (integer, optional, nullable) — Rendition width in pixels, when known.
- `height` (integer, optional, nullable) — Rendition height in pixels, when known.
- `fileBytes` (integer, optional, nullable) — File size in bytes, when known.

### FileAnalysisMetadata

Background analysis state for a file. Background analysis populates `description`, `transcript`, `durationSeconds`, and the search embedding after a file is uploaded or generated; this object lets you render a progress indicator while it runs (and skip rendering once it's done).

- `analysisLoadingState` (enum, required) — Coarse-grained analysis state. - `UNATTEMPTED`: analysis has not started yet. - `LOADING`: analysis is in progress. - `FULFILLED`: analysis completed successfully. `description`, `transcript`, and `durationSeconds` are now populated where applicable for the file's type. - `REJECTED`: analysis failed permanently and will not be retried.
  - Allowed values: `UNATTEMPTED`, `LOADING`, `FULFILLED`, `REJECTED`
- `analysisProgressPercentage` (double, required) — Progress in `[0, 100]`. Always `100` when `analysisLoadingState` is `FULFILLED`. Otherwise the most recent in-flight progress reported by the analysis task (or `0` if no progress has been reported yet).
- `analysisAttemptIndex` (integer, optional) — Zero-based index of the current analysis task attempt. Only present while analysis is still loading (`UNATTEMPTED` or `LOADING`); omitted once analysis reaches a terminal state.

### ErrorRequirement

What is needed to resolve an error, when it can be fixed by fulfilling a specific requirement (e.g. purchasing an add-on or upgrading the plan).

- `type` (string, required) — Machine-readable requirement type in snake_case (e.g. `purchase_add_on`, `upgrade_plan`).
- `details` (map from string to string, optional) — Key-value pairs with requirement-specific context (e.g. the add-on id to purchase).

### TranscriptWord

A single timed word of a transcript.

- `startSeconds` (double, required) — Start time of the word in seconds from the beginning of the audio.
- `endSeconds` (double, required) — End time of the word in seconds from the beginning of the audio. Must be greater than `startSeconds`.
- `word` (string, required) — The spoken word, used verbatim for narration timing and captions.

## Examples

**Response**

```json
{
  "exportId": "vg_expo_4bHn8pR2sY5xM1vL3tC7wd",
  "projectId": "vg_proj_9dTk3mQ1rZ7xP4vN2sB6wc",
  "status": "succeeded",
  "progressPercentage": 100,
  "attemptIndex": 0,
  "downloadUrl": "https://storage-download.videogen.io/r2dl/366ef8b7-c37a-5e04-b8ac-6c98846a70ea/primary-source?exp=1748001600&sig=exampleSignatureValue&name=Staying%20hydrated.mp4",
  "downloadUrlExpiresAt": 1748001600,
  "thumbnailUrl": "https://image-download.videogen.io/imagedl/EnMSN67Y-RVs4RhLHJA6ew/e35e641f-28c5-41ce-1d81-b271d5369201/240p?exp=1748001600&sig=exampleSignatureValue&name=thumbnail.jpg",
  "thumbnailUrlExpiresAt": 1748001600,
  "exportFileId": "vg_file_obLD1OX2eJCrEs0071Z4kA",
  "file": {
    "fileId": "vg_file_obLD1OX2eJCrEs0071Z4kA",
    "scope": "EXPORT",
    "type": "VIDEO",
    "displayName": "Staying hydrated",
    "durationSeconds": 12.5,
    "downloadUrl": "https://storage-download.videogen.io/r2dl/366ef8b7-c37a-5e04-b8ac-6c98846a70ea/primary-source?exp=1748001600&sig=exampleSignatureValue&name=Staying%20hydrated.mp4",
    "downloadUrlExpiresAt": 1748001600,
    "thumbnailUrl": "https://image-download.videogen.io/imagedl/EnMSN67Y-RVs4RhLHJA6ew/e35e641f-28c5-41ce-1d81-b271d5369201/240p?exp=1748001600&sig=exampleSignatureValue&name=thumbnail.jpg",
    "thumbnailUrlExpiresAt": 1748001600,
    "thumbnailSource": {
      "status": "ready",
      "url": "https://image-download.videogen.io/imagedl/EnMSN67Y-RVs4RhLHJA6ew/e35e641f-28c5-41ce-1d81-b271d5369201/240p?exp=1748001600&sig=exampleSignatureValue&name=thumbnail.jpg",
      "expiresAt": 1748001600,
      "width": 426,
      "height": 240
    },
    "downloadSource": {
      "status": "ready",
      "url": "https://storage-download.videogen.io/r2dl/366ef8b7-c37a-5e04-b8ac-6c98846a70ea/primary-source?exp=1748001600&sig=exampleSignatureValue&name=Staying%20hydrated.mp4",
      "expiresAt": 1748001600,
      "width": 1920,
      "height": 1080
    },
    "isPublicPreviewEnabled": false
  },
  "error": null
}
```

**SDK Code**

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

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

await client.projects.getProjectExport({
  projectId: "vg_proj_9dTk3mQ1rZ7xP4vN2sB6wc",
  exportId: "vg_expo_4bHn8pR2sY5xM1vL3tC7wd",
});
```

```python
from videogen import VideoGen

client = VideoGen(api_key="sk_videogen_live_...")

client.projects.get_project_export(
    project_id="vg_proj_9dTk3mQ1rZ7xP4vN2sB6wc",
    export_id="vg_expo_4bHn8pR2sY5xM1vL3tC7wd",
)
```