Brainstorm video ideas
brainstorm_ideasPOST/v1/brainstormsBeta
Starts writing ideas for short videos on a topic, and returns the tool run that holds them once it is done.
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 get ideas for short videos on a topic: each idea has a title, a hook, an outline, a format and why it works. Say the kind of video with videoType (get_setting_options (GET /v1/reference/setting-options) lists them), the language of the ideas and how many you want. The call answers 202 at once with the run, queued, and a Location to follow; read it with get_tool_run (GET /v1/tool-runs/{toolRunId}) (with ?wait= to hold the request) until it is done, then read the ideas in its ideas field. Always send an Idempotency-Key, the same one on every retry: a retry of the same request returns the same run and never uses a second tool run.
Example use
Each Monday a content team asks for ten ideas about its next product launch, with videoType any. It reads the hooks and outlines from get_tool_run (GET /v1/tool-runs/{toolRunId}) and picks the ones to film.
Endpoint
POST https://api.gpt-video.com/v1/brainstorms- Scope
spend. - Rate limit 10 requests a minute for each key and 20 for each account, shared by every
spendcall. See rate limits. Idempotency-Keyis required.- It starts work that runs on its own. The answer comes back before the work is done.
Parameters
Headers
| Name | Type | Required | Description |
|---|---|---|---|
Idempotency-Key | string | Required | This operation spends, so the key is required. Create it once, before the request, and send the same key on every retry. From 1 to 255 visible characters, such as a UUID. See idempotency. |
Body
| Name | Type | Required | Description |
|---|---|---|---|
topic | string | Required | What the videos are about, up to 300 characters. From 1 to 300 characters. |
tone | string | Optional | The tone of the videos, like funny or serious, up to 60 characters. At most 60 characters. |
audience | string | Optional | Who the videos are for, up to 200 characters. At most 200 characters. |
videoType | string | Required | The kind of video the ideas are for: story, fake_text, split_screen, or any. One of story, fake_text, split_screen, any. |
language | string | Required | The language of the ideas: en for English, it for Italian. One of en, it. |
count | integer | Required | How many ideas to write, from 3 to 30. From 3 to 30. |
Send only the fields listed here. Any other field is refused with UNKNOWN_PARAMETER.
Request
Ideas for story videos.
# Create the key once. Send this same key again if you retry this request.
IDEMPOTENCY_KEY=$(uuidgen)
curl -X POST "https://api.gpt-video.com/v1/brainstorms" \
-H "Authorization: Bearer $GPT_VIDEO_API_KEY" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-H "Content-Type: application/json" \
-d '{
"topic": "Morning routines for busy parents",
"videoType": "story",
"language": "en",
"count": 5
}'// Create the key once. Send this same key again if you retry this request.
const idempotencyKey = crypto.randomUUID();
const res = await fetch("https://api.gpt-video.com/v1/brainstorms", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.GPT_VIDEO_API_KEY}`,
"Idempotency-Key": idempotencyKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
"topic": "Morning routines for busy parents",
"videoType": "story",
"language": "en",
"count": 5
}),
});
const data = await res.json();
console.log(data);import os
import uuid
import requests
# Create the key once. Send this same key again if you retry this request.
idempotency_key = str(uuid.uuid4())
r = requests.post(
"https://api.gpt-video.com/v1/brainstorms",
headers={
"Authorization": f"Bearer {os.environ['GPT_VIDEO_API_KEY']}",
"Idempotency-Key": idempotency_key,
},
json={
"topic": "Morning routines for busy parents",
"videoType": "story",
"language": "en",
"count": 5
},
)
data = r.json()
print(data){
"method": "tools/call",
"params": {
"name": "brainstorm_ideas",
"arguments": {
"topic": "Morning routines for busy parents",
"videoType": "story",
"language": "en",
"count": 5,
"confirm": true,
"idempotencyKey": "REPLACE-WITH-A-NEW-UUID-FOR-THIS-CALL"
}
}
}Response
A successful call answers HTTP 202. Returns a Tool run object in toolRun.
Fields to check
| Name | Type | Description |
|---|---|---|
toolRun.id | string | The tool run id. It starts with run_. |
toolRun.status | string | queued and running are still working; done and failed are final. |
toolRun.file.downloadUrl | string or null | A link to download the file, on a read of a finished run; null otherwise. |
toolRun.file.downloadUrlExpiresAt | string or null | An ISO 8601 time in UTC. |
toolRun.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. |
paidWith | string or null | Who paid for this request: plan is the credits or the daily allowance of the account's plan, api_bonus is the API bonus. null when this request paid nothing, because the same work was already running. A retry with the same Idempotency-Key says who paid the first time. |
Response example
Location: https://api.gpt-video.com/v1/tool-runs/run_5e8a1c3f7d2b4096a1e4
{
"toolRun": {
"id": "run_5e8a1c3f7d2b4096a1e4",
"tool": "brainstorm",
"status": "queued",
"progress": 0,
"errorMessage": null,
"file": null,
"ideas": null,
"jobId": "job_2c7f9e1a4d6b48035f9e",
"createdAt": "2026-09-01T11:00:00.000Z",
"finishedAt": null,
"voiceover": null,
"separation": null,
"brainstorm": {
"topic": "Morning routines for busy parents",
"tone": "",
"audience": "",
"videoType": "story",
"language": "en",
"count": 5
}
},
"paidWith": "plan"
}All response fields
| Name | Type | Required | Description |
|---|---|---|---|
toolRun | Tool run object | Required | Described in Tool run object. |
paidWith | string or null | Required | Who paid for this request: plan is the credits or the daily allowance of the account's plan, api_bonus is the API bonus. null when this request paid nothing, because the same work was already running. A retry with the same Idempotency-Key says who paid the first time. One of plan, api_bonus. |
More examples
The tool runs of the day are used up
POST /v1/brainstorms
{
"topic": "Morning routines for busy parents",
"videoType": "any",
"language": "en",
"count": 10
}{
"error": {
"code": "DAILY_LIMIT_REACHED",
"message": "Daily limit of tool runs reached (100). It resets at 00:00 UTC. Upgrade your plan for a higher limit.",
"hint": "The limit resets at 00:00 UTC. A higher plan raises it: https://www.gpt-video.com/app/billing.",
"requestId": "req_6a2d9f1c4e8b3a7d0f5c2e94"
}
}Errors
| Code | Status | When | What to do |
|---|---|---|---|
INSUFFICIENT_CREDITS | 402 | See the error reference. | Stop and tell the user. |
PLAN_REQUIRED | 402 | See the error reference. | Stop and tell the user. |
DAILY_LIMIT_REACHED | 429 | The tool runs of the day are used up | Stop until the limit resets at 00:00 UTC. |
Every call can also answer these errors. VALIDATION_FAILED, UNKNOWN_PARAMETER, IDEMPOTENCY_KEY_REQUIRED, UNAUTHORIZED, SCOPE_MISSING, IDEMPOTENCY_IN_PROGRESS, PAYLOAD_TOO_LARGE, IDEMPOTENCY_KEY_REUSED, RATE_LIMITED, INTERNAL, UNAVAILABLE.
Cost
Uses one tool run of the plan's daily allowance, which resets at 00:00 UTC. When the API bonus pays, it also uses one bonus credit. Nothing is returned if the run fails.
- Paid by the API bonus, it uses 1 bonus credit.
- When the API bonus pays, an account can run 10 tools a day.
- See API pricing for who pays first.
Related operations
get_tool_run(GET /v1/tool-runs/{toolRunId}) Get a tool runlist_tool_runs(GET /v1/tool-runs) List the tool runsget_setting_options(GET /v1/reference/setting-options) Get the setting options
Questions
What happens if my request times out and I send it again?
Send it again with the same Idempotency-Key. You get the same run back and no second tool run is used from the daily allowance. A new key starts a new run.
Where are the ideas?
In the ideas field of the run, once get_tool_run (GET /v1/tool-runs/{toolRunId}) says it is done. Until then ideas is null.