List the tool runs
list_tool_runsGET/v1/tool-runsBeta
Lists the voiceovers, audio separations and brainstorms of the account, newest first.
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 find the tool runs of the account, for example to recover the run of a request whose answer you lost. Pass tool to see one kind only. The list is newest first and paged with cursor and limit. A page never carries download links: read a run with get_tool_run (GET /v1/tool-runs/{toolRunId}) to get one.
Example use
A script that lost the answer of a voiceover request lists the latest runs of that tool to find it again. It then reads the run with get_tool_run (GET /v1/tool-runs/{toolRunId}) to get a fresh download link.
Endpoint
GET https://api.gpt-video.com/v1/tool-runs- Scope
clips:read. - Rate limit 120 requests a minute for each key and 240 for each account, shared by every
readcall. See rate limits. - No
Idempotency-Key.
Parameters
Query
| Name | Type | Required | Description |
|---|---|---|---|
tool | string | Optional | Only the runs of this tool. Leave it out to list every tool. One of voiceover, audio_separation, brainstorm. |
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 tool runs.
curl "https://api.gpt-video.com/v1/tool-runs" \
-H "Authorization: Bearer $GPT_VIDEO_API_KEY"const res = await fetch("https://api.gpt-video.com/v1/tool-runs", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.GPT_VIDEO_API_KEY}`,
},
});
const data = await res.json();
console.log(data);import os
import requests
r = requests.get(
"https://api.gpt-video.com/v1/tool-runs",
headers={
"Authorization": f"Bearer {os.environ['GPT_VIDEO_API_KEY']}",
},
)
data = r.json()
print(data){
"method": "tools/call",
"params": {
"name": "list_tool_runs",
"arguments": {}
}
}Response
A successful call answers HTTP 200.
Fields to check
| Name | Type | Description |
|---|---|---|
data[].id | string | The tool run id. It starts with run_. |
data[].status | string | queued and running are still working; done and failed are final. |
data[].file.downloadUrl | string or null | A link to download the file, on a read of a finished run; null otherwise. |
data[].file.downloadUrlExpiresAt | string or null | An ISO 8601 time in UTC. |
data[].jobId | string or null | The job that carries out the run, to follow with get_job (GET /v1/jobs/{jobId}); 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
{
"data": [
{
"id": "run_b014441ea91a51965c46",
"tool": "voiceover",
"status": "done",
"progress": 1,
"errorMessage": null,
"voiceover": {
"title": "Launch voiceover",
"script": "Meet the editor that turns one long video into ten short clips.",
"voice": "en-aria",
"language": "en"
},
"separation": null,
"brainstorm": null,
"file": {
"assetId": "ast_e8a35ed674148f27b585",
"mimeType": "audio/mpeg",
"durationSec": 14,
"sizeBytes": 224000,
"downloadUrl": null,
"downloadUrlExpiresAt": null
},
"ideas": null,
"jobId": "job_bd92cb70ed9c45575464",
"createdAt": "2026-08-31T21:30:00.000Z",
"finishedAt": "2026-08-31T21: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[] | Tool run object | Optional | Described in Tool run object. |
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
List the voiceovers only
GET /v1/tool-runs?tool=voiceover&limit=10
{
"data": [
{
"id": "run_b014441ea91a51965c46",
"tool": "voiceover",
"status": "done",
"progress": 1,
"errorMessage": null,
"voiceover": {
"title": "Launch voiceover",
"script": "Meet the editor that turns one long video into ten short clips.",
"voice": "en-aria",
"language": "en"
},
"separation": null,
"brainstorm": null,
"file": {
"assetId": "ast_e8a35ed674148f27b585",
"mimeType": "audio/mpeg",
"durationSec": 14,
"sizeBytes": 224000,
"downloadUrl": null,
"downloadUrlExpiresAt": null
},
"ideas": null,
"jobId": "job_bd92cb70ed9c45575464",
"createdAt": "2026-08-31T21:30:00.000Z",
"finishedAt": "2026-08-31T21:32:00.000Z"
}
],
"hasMore": false,
"nextCursor": null
}Errors
Every call can also answer these errors. VALIDATION_FAILED, UNKNOWN_PARAMETER, UNAUTHORIZED, SCOPE_MISSING, RATE_LIMITED, INTERNAL, UNAVAILABLE.
Cost
No credits are used.
Related operations
get_tool_run(GET /v1/tool-runs/{toolRunId}) Get a tool runcreate_voiceover(POST /v1/voiceovers) Create a voiceoverseparate_audio(POST /v1/audio-separations) Separate the voices of a videobrainstorm_ideas(POST /v1/brainstorms) Brainstorm video ideas
Questions
Why is downloadUrl null in the list?
A page never carries download links. Read the run with get_tool_run (GET /v1/tool-runs/{toolRunId}): once it is done, every read gives a fresh downloadUrl.
Does the list include failed runs?
Yes, every run is listed with its status. A failed run has no file and no ideas; start it again with a new Idempotency-Key.