Skip to content
Create a key

Paste a key to use it in the examples on these pages. The key stays in this browser tab. These pages never send it anywhere.

Get the story of a fake text project

get_fake_text_storyGET/v1/projects/{projectId}/storyBeta

Returns the story of a fake text project, line by line, with the voice of each side and which lines have their voice.

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 read the story before you change it with update_fake_text_story (PUT /v1/projects/{projectId}/story): send back the line ids you read here to keep those lines and their voices. story is null until the project has a story. Each line says whether it has its voice; create_fake_text_voices (POST /v1/projects/{projectId}/story/voices) makes the missing ones.

Example use

Before it fixes a typo in one line, a script reads the story and keeps every line id. It sends the story back with those ids through update_fake_text_story (PUT /v1/projects/{projectId}/story), so only the corrected line loses its voice.

Endpoint

Code
GET https://api.gpt-video.com/v1/projects/{projectId}/story
  • 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.
  • No Idempotency-Key.

Parameters

Path

NameTypeRequiredDescription
projectIdstringRequiredThe project id. It starts with prj_. Matches ^prj_[0-9a-f]{20}$.

Request

Read the story.

Request example
curl "https://api.gpt-video.com/v1/projects/prj_ba8b07a88bfb14585459/story" \
  -H "Authorization: Bearer $GPT_VIDEO_API_KEY"
const res = await fetch("https://api.gpt-video.com/v1/projects/prj_ba8b07a88bfb14585459/story", {
  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/projects/prj_ba8b07a88bfb14585459/story",
    headers={
        "Authorization": f"Bearer {os.environ['GPT_VIDEO_API_KEY']}",
    },
)
data = r.json()
print(data)
{
  "method": "tools/call",
  "params": {
    "name": "get_fake_text_story",
    "arguments": {
      "projectId": "prj_ba8b07a88bfb14585459"
    }
  }
}

Response

A successful call answers HTTP 200.

Fields to check

NameTypeDescription
story.idstringThe story id. It starts with cnv_.
story.messages[].idstringThe line id. Send it back with update_fake_text_story (PUT /v1/projects/{projectId}/story) to keep the line and its voice.

Response example

HTTP 200
{
  "story": {
    "id": "cnv_a744d5ef6cc005e19285",
    "projectId": "prj_ba8b07a88bfb14585459",
    "title": "The surprise party",
    "contactName": "Sam",
    "language": "en",
    "left": {
      "name": "Sam"
    },
    "right": {
      "name": "Me"
    },
    "voices": {
      "left": "en-guy",
      "right": "en-aria"
    },
    "messages": [
      {
        "id": "msg_e09afef44e32faf0bcb7",
        "side": "left",
        "text": "Are you free on Saturday night?",
        "voiced": true,
        "voiceDurationSec": 1.9
      },
      {
        "id": "msg_568316dbc0cca81d3b24",
        "side": "right",
        "text": "Maybe, why?",
        "voiced": false,
        "voiceDurationSec": null
      },
      {
        "id": "msg_556466181cf09d6bf0a2",
        "side": "left",
        "text": "No reason. Wear something nice.",
        "voiced": true,
        "voiceDurationSec": 1.9
      },
      {
        "id": "msg_0d93572450a652e08706",
        "side": "right",
        "text": "Now I am worried.",
        "voiced": false,
        "voiceDurationSec": null
      }
    ],
    "voicedCount": 2,
    "createdAt": "2026-08-31T22:12:00.000Z",
    "updatedAt": "2026-08-31T22:14:00.000Z"
  }
}
All response fields
NameTypeRequiredDescription
storyobject or nullRequiredThe story of the project; null until it has one.
story.idstringRequiredThe story id. It starts with cnv_.
story.projectIdstringRequired
story.titlestringRequired
story.contactNamestringRequiredThe name shown at the top of the chat.
story.languagestringRequiredOne of en, it.
story.leftobjectRequiredThe other person in the chat.
story.rightobjectRequiredThe person whose phone shows the chat.
story.voicesobjectRequiredThe voice of each side, as list_voices (GET /v1/reference/voices) names it; null for the default voice of the language, or for a voice that is not available through the API.
story.messagesarray of objectsRequired
story.voicedCountintegerRequiredHow many lines have their voice.
story.createdAtstringRequiredAn ISO 8601 time in UTC.
story.updatedAtstringRequiredAn ISO 8601 time in UTC.
Fields of story.left
NameTypeRequiredDescription
story.left.namestringRequired
Fields of story.right
NameTypeRequiredDescription
story.right.namestringRequired
Fields of story.voices
NameTypeRequiredDescription
story.voices.leftstring or nullRequired
story.voices.rightstring or nullRequired
Fields of story.messages[]
NameTypeRequiredDescription
story.messages[].idstringRequiredThe line id. Send it back with update_fake_text_story (PUT /v1/projects/{projectId}/story) to keep the line and its voice.
story.messages[].sidestringRequiredOne of left, right.
story.messages[].textstringRequired
story.messages[].voicedbooleanRequiredtrue when the line has its voice.
story.messages[].voiceDurationSecnumber or nullRequiredHow long the voice of the line lasts, in seconds; null without a voice.
More examples

A project with no story yet

GET /v1/projects/prj_ba8b07a88bfb14585459/story

HTTP 200
{
  "story": null
}

A project that is not a fake text project

GET /v1/projects/prj_7c2e9a4f1b3d4e8096a5/story

HTTP 409
{
  "error": {
    "code": "CONFLICT",
    "message": "This project is not a fake text project. Stories exist only in fake text projects.",
    "requestId": "req_6e2a9c0d4b7f41583a1e9d6c"
  }
}

Errors

CodeStatusWhenWhat to do
NOT_FOUND404See the error reference.Change the request, then send it again.
CONFLICT409A project that is not a fake text projectRead the resource again, then decide. Do not send the same request again.

Every call can also answer these errors. VALIDATION_FAILED, UNKNOWN_PARAMETER, UNAUTHORIZED, SCOPE_MISSING, RATE_LIMITED, INTERNAL, UNAVAILABLE.

Cost

No credits are used.

Questions

Does a line keep its voice when I change its words?

It keeps the old voice until create_fake_text_voices (POST /v1/projects/{projectId}/story/voices) makes a new one for the new words. Lines whose words do not change are not voiced again.

Why is the voice of a side null?

null is the default voice of the language. It is also null when the project uses a voice that is not offered through the API; choose one with update_fake_text_story (PUT /v1/projects/{projectId}/story).

View as Markdown