---
title: "Get a project | GPT-Video API reference"
description: "Returns one project with its status, settings, missing settings and the analysis running on it."
url: "https://www.gpt-video.com/developers/api/get-project"
operation: "get_project"
method: "GET"
path: "/v1/projects/{projectId}"
scope: "clips:read"
---

Do not assume endpoints have parameters other than the ones explicitly specified.

# Get a project

Operation id `get_project`. Request `GET /v1/projects/{projectId}`.

Returns one project with its status, settings, missing settings and the analysis running on it.

Beta. This endpoint is supported and can gain new fields. If a change would break your code, we tell you before it takes effect and list it in the changelog.

## About

Use it to check whether a project is ready to analyze (missingSettings is empty), whether an analysis is running (analysisJobId), and why the last analysis failed (errorMessage). To wait for an analysis, follow its job with get_job (`GET /v1/jobs/{jobId}`).

## Example use

A script reads a project before it starts the analysis and checks that missingSettings is empty. After a failed analysis it reads errorMessage to tell the person what to change.

## Endpoint

```text
GET https://api.gpt-video.com/v1/projects/{projectId}
```

- Scope `clips:read`.
- Rate limit 120 requests a minute for each key and 240 for each account, shared by every `read` call. See [rate limits](/developers/rate-limits.md).
- No `Idempotency-Key`.

## Parameters

### Path

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `projectId` | string | Required | The project id. It starts with prj_. Matches `^prj_[0-9a-f]{20}$`. |

## Request

Read a project.

```bash title="curl"
curl "https://api.gpt-video.com/v1/projects/prj_7c2e9a4f1b3d4e8096a5" \
  -H "Authorization: Bearer $GPT_VIDEO_API_KEY"
```

```ts title="TypeScript"
const res = await fetch("https://api.gpt-video.com/v1/projects/prj_7c2e9a4f1b3d4e8096a5", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${process.env.GPT_VIDEO_API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
```

```python title="Python"
import os

import requests

r = requests.get(
    "https://api.gpt-video.com/v1/projects/prj_7c2e9a4f1b3d4e8096a5",
    headers={
        "Authorization": f"Bearer {os.environ['GPT_VIDEO_API_KEY']}",
    },
)
data = r.json()
print(data)
```

## Response

A successful call answers HTTP 200.

### Fields to check

| Name | Type | Description |
| --- | --- | --- |
| `project.id` | string | The project id. It starts with prj_. |
| `project.status` | string | draft has not been analyzed yet, processing is being analyzed, ready has clips, failed means the last analysis failed and errorMessage says why. |
| `project.analysisJobId` | string or null | The job of the analysis running on the project now, to follow with get_job (`GET /v1/jobs/{jobId}`); null when none is running. |

### Response example

```json title="HTTP 200"
{
  "project": {
    "id": "prj_7c2e9a4f1b3d4e8096a5",
    "kind": "autoclip",
    "title": "Founder interview",
    "status": "ready",
    "sourceAssetId": "ast_3f9a1c7e5b2d4086a1c4",
    "compositionId": null,
    "settings": {
      "language": "en",
      "clipCount": 3,
      "minDurationSec": 15,
      "maxDurationSec": 60,
      "objective": "viral",
      "captionStyle": "word-pop",
      "reframe": "face",
      "instructions": null,
      "vocabulary": null
    },
    "missingSettings": [],
    "splitScreen": null,
    "streamer": null,
    "redditStory": null,
    "fakeText": null,
    "vibeEdit": null,
    "errorMessage": null,
    "createdAt": "2026-09-01T09:10:00.000Z",
    "updatedAt": "2026-09-01T09:40:00.000Z",
    "analysisJobId": null
  }
}
```

**All response fields**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project` | object | Required |   |
| `project.id` | string | Required | The project id. It starts with prj_. |
| `project.kind` | string | Required | The kind of project: autoclip finds clips in a long video, splitscreen, streamer and redditstory build one video, faketext shows a chat story, vibeedit is an edit of a video. Each kind has its own operations; projects made in the GPT-Video app are listed too. One of `autoclip`, `splitscreen`, `faketext`, `redditstory`, `streamer`, `vibeedit`. |
| `project.title` | string | Required | The name of the project. |
| `project.status` | string | Required | draft has not been analyzed yet, processing is being analyzed, ready has clips, failed means the last analysis failed and errorMessage says why. One of `draft`, `processing`, `ready`, `failed`. |
| `project.sourceAssetId` | string or null | Required | The video the project is made from: the source of an Auto Clip, streamer or Vibe Editing project, the main video of a split screen project. null for Reddit story and fake text projects, whose background video is in their block, until an Auto Clip project has a source, and when the file no longer exists or cannot be used through the API. |
| `project.compositionId` | string or null | Required | The composition of a split screen, streamer, Reddit story, fake text or Vibe Editing project, to export with create_export (`POST /v1/compositions/{compositionId}/exports`). null for an Auto Clip project, whose compositions belong to its accepted clips, and for a project that has no composition yet. |
| `project.settings` | object or null | Required | The settings of an Auto Clip project; null for every other kind. |
| `project.missingSettings` | array of strings | Required | The settings still to choose before the project can be analyzed. Empty when nothing is missing, and for every kind other than autoclip. |
| `project.splitScreen` | object or null | Required | The choices of a split screen project; null for every other kind. |
| `project.streamer` | object or null | Required | The choices of a streamer project; null for every other kind. |
| `project.redditStory` | object or null | Required | The post, the voice and the choices of a Reddit story project; null for every other kind. |
| `project.fakeText` | object or null | Required | The choices of a fake text project; null for every other kind. |
| `project.vibeEdit` | object or null | Required | The choices of a Vibe Editing project; null for every other kind. |
| `project.errorMessage` | string or null | Required | Why the last analysis failed, in one sentence; null unless the status is failed. |
| `project.createdAt` | string | Required | An ISO 8601 time in UTC. |
| `project.updatedAt` | string | Required | An ISO 8601 time in UTC. |
| `project.analysisJobId` | string or null | Required | The job of the analysis running on the project now, to follow with get_job (`GET /v1/jobs/{jobId}`); null when none is running. |

**Fields of project.settings**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project.settings.language` | string or null | Required | The language spoken in the video: en, it, or auto to detect it. null until it is chosen. One of `auto`, `it`, `en`. |
| `project.settings.clipCount` | integer or null | Required | How many clips the analysis proposes. null until it is chosen. |
| `project.settings.minDurationSec` | number or null | Required | The shortest clip the analysis may propose, in seconds. null until it is chosen. |
| `project.settings.maxDurationSec` | number or null | Required | The longest clip the analysis may propose, in seconds. null until it is chosen. |
| `project.settings.objective` | string or null | Required | What the clips should be good at. get_setting_options (`GET /v1/reference/setting-options`) lists every objective with what it means. null until it is chosen. One of `viral`, `educational`, `entertaining`, `emotional`, `controversial`, `howto`, `business`. |
| `project.settings.captionStyle` | string or null | Required | The caption style of the clips. get_setting_options (`GET /v1/reference/setting-options`) lists every style with what it looks like. null until it is chosen. One of `bold-karaoke`, `word-pop`, `boxed`, `outline`. |
| `project.settings.reframe` | string or null | Required | How a clip follows the speaker: face follows the face of the speaker, center keeps the middle of the frame. null until it is chosen. One of `face`, `center`. |
| `project.settings.instructions` | string or null | Required | Free text that tells the analysis what to look for, such as only the moments where a given person speaks. null when there are none. |
| `project.settings.vocabulary` | string or null | Required | Names, brands and jargon the transcription should spell right, separated by commas. It is used when the video is transcribed, so set it before the first analysis. null when there is none. |

**Fields of project.splitScreen**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project.splitScreen.mainAssetId` | string or null | Required | The main video, shown on top and transcribed for the captions. null when the file no longer exists or cannot be used through the API. |
| `project.splitScreen.backgroundAssetId` | string or null | Required | The background video, shown under the main video. null when the file no longer exists or cannot be used through the API. |
| `project.splitScreen.layout` | string | Required | How the screen is split: 50-50 gives each video half the screen, 60-40 gives the main video more. One of `50-50`, `60-40`. |
| `project.splitScreen.captionStyle` | string or null | Required | The caption style; null when the video has no captions. One of `bold-karaoke`, `word-pop`, `boxed`, `outline`. |
| `project.splitScreen.language` | string | Required | The language spoken in the main video: en, it, or auto to detect it. One of `auto`, `it`, `en`. |
| `project.splitScreen.backgroundStartSec` | number or null | Required | Where the background video starts, in seconds; null until the first build chooses a random start, which is then kept. |
| `project.splitScreen.vocabulary` | string or null | Required | Names, brands and jargon the transcription should spell right, separated by commas; null when there are none. |

**Fields of project.streamer**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project.streamer.sourceAssetId` | string or null | Required | The clip the project is made from. null when the file no longer exists or cannot be used through the API. |
| `project.streamer.headline` | string | Required | The line shown over the clip; empty for none. |
| `project.streamer.language` | string | Required | The language spoken in the clip: en, it, or auto to detect it. One of `auto`, `it`, `en`. |
| `project.streamer.captionStyle` | string | Required | The caption style. One of `bold-karaoke`, `word-pop`, `boxed`, `outline`. |
| `project.streamer.reframe` | string | Required | How the video follows the speaker: face follows the face, center keeps the middle of the frame. One of `face`, `center`. |
| `project.streamer.vocabulary` | string or null | Required | Names, brands and jargon the transcription should spell right, separated by commas; null when there are none. |

**Fields of project.redditStory**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project.redditStory.postTitle` | string | Required | The title of the post, shown on the title card. |
| `project.redditStory.postBody` | string | Required | The text of the post, read by the voice. |
| `project.redditStory.author` | string | Required | The author shown on the title card. |
| `project.redditStory.subreddit` | string | Required | The community shown on the title card. |
| `project.redditStory.voice` | string or null | Required | The voice that reads the story, as list_voices (`GET /v1/reference/voices`) names it; null when the project uses a voice that is not available through the API. |
| `project.redditStory.language` | string | Required | The language of the story and of its voice. One of `en`, `it`. |
| `project.redditStory.backgroundAssetId` | string or null | Required | The background video. null when the file no longer exists or cannot be used through the API. |
| `project.redditStory.captionStyle` | string | Required | The caption style. One of `bold-karaoke`, `word-pop`, `boxed`, `outline`. |
| `project.redditStory.vocabulary` | string or null | Required | Names, brands and jargon the transcription should spell right, separated by commas; null when there are none. |

**Fields of project.fakeText**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project.fakeText.theme` | string | Required | How the chat looks: imessage or whatsapp. One of `imessage`, `whatsapp`. |
| `project.fakeText.language` | string | Required | The language of the story and of its voices. One of `en`, `it`. |
| `project.fakeText.voiceover` | boolean | Required | true when create_fake_text_voices (`POST /v1/projects/{projectId}/story/voices`) makes voices for the lines. |
| `project.fakeText.backgroundAssetId` | string or null | Required | The background video behind the chat. null when the file no longer exists or cannot be used through the API. |
| `project.fakeText.storyId` | string or null | Required | The story of the project, read with get_fake_text_story (`GET /v1/projects/{projectId}/story`); null until the project has one. |

**Fields of project.vibeEdit**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `project.vibeEdit.sourceAssetId` | string or null | Required | The video the edit starts from. null when the file no longer exists or cannot be used through the API. |
| `project.vibeEdit.language` | string | Required | The language spoken in the video: en, it, or auto to detect it. One of `auto`, `it`, `en`. |
| `project.vibeEdit.captionStyle` | string | Required | The caption style the edit starts with. One of `bold-karaoke`, `word-pop`, `boxed`, `outline`. |
| `project.vibeEdit.aspect` | string | Required | The shape the edit starts with: source keeps the shape of the video. One of `source`, `9:16`, `1:1`, `16:9`. |
| `project.vibeEdit.vocabulary` | string or null | Required | Names, brands and jargon the transcription should spell right, separated by commas; null when there are none. |
| `project.vibeEdit.prepared` | boolean | Required | true once prepare_timeline (`POST /v1/projects/{projectId}/timeline/prepare`) has prepared the edit; an edit is never prepared or charged again. |

**More examples**

#### A project that does not exist

`GET /v1/projects/prj_9f0d3b7e1c5a4d28b6f3`

```json title="HTTP 404"
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Project prj_9f0d3b7e1c5a4d28b6f3 not found",
    "hint": "Check the id. An id that belongs to another account is not found either.",
    "requestId": "req_33121f31bec52069f18c83ed"
  }
}
```

## Errors

| Code | Status | When | What to do |
| --- | --- | --- | --- |
| [`NOT_FOUND`](/developers/errors.md#NOT_FOUND) | 404 | A project that does not exist | Change the request, then send it again. |

Every call can also answer these errors. [`VALIDATION_FAILED`](/developers/errors.md#VALIDATION_FAILED), [`UNKNOWN_PARAMETER`](/developers/errors.md#UNKNOWN_PARAMETER), [`UNAUTHORIZED`](/developers/errors.md#UNAUTHORIZED), [`SCOPE_MISSING`](/developers/errors.md#SCOPE_MISSING), [`RATE_LIMITED`](/developers/errors.md#RATE_LIMITED), [`INTERNAL`](/developers/errors.md#INTERNAL), [`UNAVAILABLE`](/developers/errors.md#UNAVAILABLE).

## Cost

No credits are used.

## Related operations

- [`update_project`](/developers/api/update-project.md) (`PATCH /v1/projects/{projectId}`) Update a project
- [`analyze_project`](/developers/api/analyze-project.md) (`POST /v1/projects/{projectId}/analyze`) Analyze a project
- [`get_job`](/developers/api/get-job.md) (`GET /v1/jobs/{jobId}`) Get a job
- [`list_clips`](/developers/api/list-clips.md) (`GET /v1/projects/{projectId}/clips`) List the clips of a project
- [`list_projects`](/developers/api/list-projects.md) (`GET /v1/projects`) List projects
- [`estimate_analysis`](/developers/api/estimate-analysis.md) (`POST /v1/projects/{projectId}/analyze/estimate`) Estimate the credits of an analysis or a build

## Questions

### How do I know when a project is ready to analyze?

When missingSettings is empty and the project has a sourceAssetId. estimate_analysis (`POST /v1/projects/{projectId}/analyze/estimate`) also tells you the price and whether the account has enough credits.

### Why does a project of another kind have no settings?

settings and missingSettings are the settings of an Auto Clip analysis, so they are filled for autoclip only. The choices of every other kind are in the block named after it, such as splitScreen or vibeEdit.
