Migrate from V1 to V2

Move synchronous video generation integrations to the asynchronous API

The V1 video generation endpoints listed below are being deprecated. Migrate your integration to V2 before the deadline in your deprecation notice.

V2 uses the same authentication and generation request parameters as V1. The main change is the response flow: V1 keeps one HTTP request open and returns the generated file, while V2 creates a background job that you poll for its result.

Endpoint mapping

Change the version in each generation endpoint:

V1 endpointV2 endpoint
POST /v1/text-to-videoPOST /v2/text-to-video
POST /v1/image-to-videoPOST /v2/image-to-video
POST /v1/audio-to-videoPOST /v2/audio-to-video
POST /v1/retakePOST /v2/retake
POST /v1/extendPOST /v2/extend

The media upload endpoint remains POST /v1/upload. You do not need to change uploaded ltx:// URIs or replace /v1/upload as part of this migration.

What changes

V1V2
POST returns 200 OK after generation finishes.POST returns 202 Accepted immediately.
The response body is the generated MP4 file.The response body is JSON containing a job id.
One connection remains open during generation.Poll GET /v2/{endpoint}/{id} until the job finishes.
A generation failure is returned by the original request.A generation failure appears as status: "failed" with an error object.
Concurrency limits can return concurrency_limit_error.Queue limits can return rate_limit_error.

Your API key, request body, model selection, input URIs, and pricing do not change.

Migrate a request

For example, this V1 request waits for generation and writes the response body directly to a file:

1import requests
2
3response = requests.post(
4 "https://api.ltx.io/v1/text-to-video",
5 headers={"Authorization": "Bearer YOUR_API_KEY"},
6 json={
7 "prompt": "A majestic eagle soaring through clouds at sunset",
8 "model": "ltx-2-5-pro",
9 "duration": 8,
10 "resolution": "1920x1080",
11 },
12)
13response.raise_for_status()
14
15with open("video.mp4", "wb") as output:
16 output.write(response.content)

With V2, send the same body to the V2 endpoint. The response contains a job ID:

1import requests
2
3response = requests.post(
4 "https://api.ltx.io/v2/text-to-video",
5 headers={"Authorization": "Bearer YOUR_API_KEY"},
6 json={
7 "prompt": "A majestic eagle soaring through clouds at sunset",
8 "model": "ltx-2-5-pro",
9 "duration": 8,
10 "resolution": "1920x1080",
11 },
12)
13response.raise_for_status()
14job = response.json()
202 Accepted
1{
2 "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
3 "created_at": "2026-09-06T12:00:00.000Z"
4}

Poll the matching endpoint with that ID:

1response = requests.get(
2 f"https://api.ltx.io/v2/text-to-video/{job['id']}",
3 headers={"Authorization": "Bearer YOUR_API_KEY"},
4)
5response.raise_for_status()
6job = response.json()

When status is completed, download the output from result.video_url:

Completed job
1{
2 "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
3 "status": "completed",
4 "created_at": "2026-09-06T12:00:00.000Z",
5 "completed_at": "2026-09-06T12:02:30.000Z",
6 "result": {
7 "video_url": "https://storage.googleapis.com/example/video.mp4"
8 }
9}

Update your application flow

Replace code that reads a video from the POST response with a submit, poll, and download loop.

We recommend waiting at least 5 seconds between polls. Choose a slightly different delay each time, to spread out requests when polling multiple jobs. Stop when the status is completed or failed.

These minimal examples stop on HTTP errors. The cURL version uses jq to read fields out of the JSON responses. For production, add retries for polling and downloads as described in the production checklist.

1import random
2import time
3import requests
4
5api_key = "YOUR_API_KEY"
6headers = {"Authorization": f"Bearer {api_key}"}
7endpoint = "text-to-video"
8
9submit_response = requests.post(
10 f"https://api.ltx.io/v2/{endpoint}",
11 headers={**headers, "Content-Type": "application/json"},
12 json={
13 "prompt": "A majestic eagle soaring through clouds at sunset",
14 "model": "ltx-2-5-pro",
15 "duration": 8,
16 "resolution": "1920x1080",
17 },
18)
19submit_response.raise_for_status()
20job = submit_response.json()
21
22while True:
23 time.sleep(random.uniform(5, 6))
24 poll_response = requests.get(
25 f"https://api.ltx.io/v2/{endpoint}/{job['id']}",
26 headers=headers,
27 )
28 poll_response.raise_for_status()
29 job = poll_response.json()
30
31 if job["status"] == "completed":
32 break
33 if job["status"] == "failed":
34 raise RuntimeError(job["error"]["message"])
35
36video_response = requests.get(job["result"]["video_url"])
37video_response.raise_for_status()
38with open("video.mp4", "wb") as output:
39 output.write(video_response.content)

Production checklist

  • Use the recommended polling interval above and stop on both completed and failed.
  • Retry transient network and 5xx errors on polling and download GET requests with exponential backoff.
  • Handle errors from both the initial POST and a job with status: "failed".
  • Download or re-host outputs as soon as the job completes. Job status is kept for up to 24 hours, and output URLs expire independently of job status. See retention.
  • Update handling for 429 responses. V2 can return rate_limit_error when your organization’s job queue is full.
  • Keep logging the x-request-id response header. See Debugging Requests.
  • Test each endpoint your integration uses before switching production traffic.

See Async Jobs for the complete job lifecycle and Error Handling for retry guidance and error types.