---
title: "List the Editor Assistant turns of a project | GPT-Video API"
description: "Lists the turns of the Editor Assistant on a project, newest first, the ones sent from the app included."
url: "https://www.gpt-video.com/developers/api/list-assistant-turns"
operation: "list_assistant_turns"
method: "GET"
path: "/v1/projects/{projectId}/assistant/turns"
scope: "clips:read"
---

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

# List the Editor Assistant turns of a project

Operation id `list_assistant_turns`. Request `GET /v1/projects/{projectId}/assistant/turns`.

Lists the turns of the Editor Assistant on a project, newest first, the ones sent from the app included.

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

Call this to read the conversation of a project with the Editor Assistant, for example to recover the turn of a request whose answer you lost. A project has one conversation, shared with the GPT-Video app, so the list holds the turns sent from the app as well as the ones sent through the API. The list is newest first and paged with cursor and limit.

## Example use

A tool that lost the id of a turn after a restart lists the conversation of the project, finds the last request it sent, and goes on following that turn instead of asking the Editor Assistant again.

## Endpoint

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

- 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 id of the project the Editor Assistant works on. Matches `^prj_[0-9a-f]{20}$`. |

### Query

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `limit` | integer | Optional | How many items to return, from 1 to 100. Defaults to 20. From 1 to 100. Default `20`. |
| `cursor` | string | Optional | The nextCursor value from the previous page. Leave it out to get the first page. From 1 to 512 characters. |

## Request

List the turns of a project.

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

```ts title="TypeScript"
const res = await fetch("https://api.gpt-video.com/v1/projects/prj_b9c1f9c7873dcef51a57/assistant/turns", {
  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_b9c1f9c7873dcef51a57/assistant/turns",
    headers={
        "Authorization": f"Bearer {os.environ['GPT_VIDEO_API_KEY']}",
    },
)
data = r.json()
print(data)
```

```json title="MCP (Full)"
{
  "method": "tools/call",
  "params": {
    "name": "list_assistant_turns",
    "arguments": {
      "projectId": "prj_b9c1f9c7873dcef51a57"
    }
  }
}
```

## Response

A successful call answers HTTP 200.

### Fields to check

| Name | Type | Description |
| --- | --- | --- |
| `data[].id` | string | The turn id. It starts with agm_. |
| `data[].status` | string | queued and running are still working; done, failed and cancelled are final. |
| `data[].actions[].id` | string | The action id. It starts with tc_. |
| `data[].actions[].status` | string |   |
| `data[].jobId` | string or null | The job that runs the turn; null once it is gone. |
| `hasMore` | boolean | true when there are more items after this page. |
| `nextCursor` | string or null | Send it as cursor to get the next page. It is null on the last page. |

### Response example

```json title="HTTP 200"
{
  "data": [
    {
      "id": "agm_1e3d5feef4076b4329cf",
      "projectId": "prj_b9c1f9c7873dcef51a57",
      "status": "done",
      "message": "Make the captions bolder.",
      "reply": "I switched the captions to the bold karaoke style.",
      "outcome": "done",
      "question": null,
      "options": [],
      "actions": [
        {
          "id": "tc_6c98ac1c068fc322b284",
          "tool": "set_captions",
          "status": "done",
          "summary": "Captions: bold karaoke",
          "undoable": true,
          "creditsReturned": 0
        }
      ],
      "jobId": "job_0724f7cc56c41f889a0c",
      "errorMessage": null,
      "createdAt": "2026-08-31T22:31:00.000Z",
      "finishedAt": "2026-08-31T22:32:00.000Z"
    }
  ],
  "hasMore": false,
  "nextCursor": null
}
```

**All response fields**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `data` | array of objects | Required | The items of this page. |
| `data[]` | Assistant turn object | Optional | Described in [Assistant turn object](/developers/objects.md#assistant-turn). |
| `hasMore` | boolean | Required | true when there are more items after this page. |
| `nextCursor` | string or null | Required | Send it as cursor to get the next page. It is null on the last page. |

**More examples**

#### A project that does not exist

`GET /v1/projects/prj_9f0d3b7e1c5a4d28b6f3/assistant/turns`

```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_9c4f1a7e3b8d2c6f0a5e1b93"
  }
}
```

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

- [`get_assistant_turn`](/developers/api/get-assistant-turn.md) (`GET /v1/assistant/turns/{turnId}`) Get an Editor Assistant turn
- [`create_assistant_turn`](/developers/api/create-assistant-turn.md) (`POST /v1/projects/{projectId}/assistant/turns`) Send a message to the Editor Assistant

## Questions

### Why do I see turns I did not send?

The conversation of a project is shared with the GPT-Video app: the turns its users sent there are in the list too.

### How do I find the turn of a request whose answer I lost?

Send the same request again with the same Idempotency-Key: you get the same turn back and nothing is used. Or read this list: the newest turns come first, with the message each one answers.
