Video Extension with /v1/videos/extensions
On this page
Lesson updated November 2, 2026 based on the xAI Video API reference: the extension receives the video in a
videoobject ({"url": ...}), exactly like editing—the previous text claimed the opposite—the result is read fromvideo.url, and the source is limited to 15 seconds. Sources: Video Extension · Video Reference.
Extending an existing video
Where editing transforms a sequence without changing its length, extension does the exact opposite: it lengthens a video by generating a continuation consistent with what came before. This solves the most common problem in video generation—a successful clip that’s too short, or a scene that deserves to develop beyond its initial duration. Rather than regenerating everything and hoping to recreate the same look, you start from what exists and continue.
The POST /v1/videos/extensions endpoint
The request resembles a generation request, with the starting video added.
{
"model": "grok-imagine-video",
"prompt": "Continue the scene with a zoom out revealing the full landscape",
"video": {"url": "https://exemple.com/video-courte.mp4"},
"duration": 5
}
The model field remains grok-imagine-video, prompt describes what should happen in the continuation, the video object specifies the video to extend (a url or the file_id of an uploaded file, for a source of 2 to 15 seconds), and duration sets the extension length between 2 and 10 seconds—the default is 6 seconds. Unlike editing, you regain control over duration here. The returned video contains the original followed by the extension: a 10-second source extended by 5 seconds yields a 15-second video.
The following table summarizes what separates the two endpoints, since confusion is common.
| Aspect | Editing (/edits) | Extension (/extensions) |
|---|---|---|
| Objective | Modify content | Add duration |
| Video parameter | video object (url or file_id) | video object (url or file_id) |
| Source duration | Max 8.7 s | 2 to 15 s |
| Output duration | Same as source (Max 720p) | Source + 2 to 10 s |
| Original content | Modifies | Preserves |
Both REST API endpoints receive the video the same way, in a video object with a url property. The Python SDK, however, takes it as the video_url parameter: do not copy this parameter name into a JSON body, the API won’t recognize it. What truly distinguishes the two endpoints is the duration.
Three ways to continue a scene
The simplest case consists of letting what is already happening continue. The prompt picks up the current action and extends it without a break.
{
"model": "grok-imagine-video",
"prompt": "The character continues walking along the beach, waves rolling gently",
"video": {"url": "https://exemple.com/promenade.mp4"},
"duration": 6
}
You can also introduce a change, meaning bringing in a new element or modifying the direction of view. This gives a sequence its narrative progression.
{
"model": "grok-imagine-video",
"prompt": "The camera pivots right revealing a lighthouse in the distance, the lighthouse beam starts to rotate",
"video": {"url": "https://exemple.com/plage.mp4"},
"duration": 8
}
Third use case, the conclusion: a short extension that closes the sequence cleanly, often with a fade.
{
"model": "grok-imagine-video",
"prompt": "The scene ends with a gradual fade to black, the last glimmers of sunlight disappear on the horizon",
"video": {"url": "https://exemple.com/coucher-soleil.mp4"},
"duration": 4
}
Chaining extensions to build a sequence
Nothing prevents extending a video multiple times in a row. Each extension produces a new video whose URL can serve as the source for the next extension, letting you build a long sequence via successive segments, each driven by its own prompt. The script below chains three extensions by reinjecting the obtained URL at each step.
import httpx
import time
api_key = "your_key"
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
def attendre_video(request_id):
"""Poll status until completion."""
while True:
resp = httpx.get(
f"https://api.x.ai/v1/videos/{request_id}",
headers=headers
).json()
if resp["status"] == "done":
return resp["video"]["url"]
if resp["status"] == "failed":
raise RuntimeError(f"Generation failed: {resp.get('error')}")
time.sleep(5)
# Base video
video_url = "https://exemple.com/video-initiale.mp4"
# Chain 3 extensions
prompts = [
"The character crosses the bridge, profile view",
"He stops in the middle and looks at the river below",
"He resumes walking toward the other bank, the camera follows"
]
for prompt in prompts:
resp = httpx.post(
"https://api.x.ai/v1/videos/extensions",
headers=headers,
json={
"model": "grok-imagine-video",
"prompt": prompt,
"video": {"url": video_url},
"duration": 5
}
).json()
video_url = attendre_video(resp["request_id"])
print(f"Extension complete: {video_url}")
This elegance comes at a price, literally and figuratively. Each extension is billed separately. The source cannot exceed 15 seconds, which bounds the chain: starting from 5 seconds, the sequence reaches 20 seconds after three 5-second extensions, and a fourth would be refused. Visual coherence degrades across the links, since each step relies on an already interpreted output: beyond three or four chained extensions, color and morphology drifts become visible. And as everywhere in this API, URLs are temporary—download each intermediate version, otherwise a failure at the end of the chain will force you to start over from the beginning.
The generation then extension duo
The most common pattern in production combines both endpoints. You first generate a short 3-second base with a very precise prompt, via POST /v1/videos/generations, letting you iterate on the starting aesthetic at lower cost. You then add 5 seconds of development via POST /v1/videos/extensions, then 4 seconds of conclusion via a second call to the same endpoint. The result is a 12-second video built segment by segment, where each part was validated before the next was engaged—control that no single 12-second generation would offer.
Key points to remember
- Extension lengthens a 2 to 15-second video by a 2 to 10-second segment (default 6), and returns the complete video
- The source video goes in a
videoobject (urlorfile_id), like editing; the Python SDK takes it asvideo_url - Chaining allows creating long sequences step by step
- Coherence degrades beyond 3-4 successive extensions
- Combine initial generation + extensions for precise content control