Your First Generation
- →Name the four required parameters for text-to-video and the three optional ones with their defaults
- →Make one clip end to end on the path that matches your track
- →Explain when a synchronous request is the right call and when it is not
- →Predict the cost of a generation before submitting it
The four decisions
Whichever track you are on, a generation is the same four decisions. The API calls them required parameters; a console form calls them fields; they are the same four.
- `prompt` — up to 5000 characters.
- `model` —
ltx-2-3-proorltx-2-3-fast. - `duration` — an integer, in seconds, inside the cap from f2.
- `resolution` — a string, e.g.
"1920x1080".
Three optional parameters matter from the first request:
- `fps` — integer, defaults to 24.
- `generate_audio` — boolean, defaults to true.
- `camera_motion` — an enum; f5 covers all eight values.
Two of those defaults deserve a beat. generate_audio: true means you get sound whether or not you thought about it. Playing your first result with the speakers muted and calling it done is how people ship a clip with a soundtrack they never heard. And fps: 24 is not a neutral default — it is one of the two frame rates that unlock Fast's 20-second ceiling at 1080p, so raising it silently halves your duration limit.
For image-to-video, the same base plus a required `image_uri`, and an optional `last_frame_uri` that is LTX-2.3-only — it does not exist on the legacy ltx-2-* models. First-to-last-frame control is one of the concrete things you gain by migrating.
If you're on the Developer track
Your first call should be synchronous. Submit, block, get a video.
A common claim is that only the async /v2 endpoints exist and every generation therefore requires a submit-poll-download loop. Not true. Synchronous `/v1` versions exist for text-to-video, image-to-video, audio-to-video, retake, and extend, and they return the binary video directly — no polling, no job id. Only reframe and HDR are async-only. If you built a polling client before checking, you wrote code you did not need.
curl -sS -X POST https://api.ltx.io/v1/text-to-video \
-H "Authorization: Bearer $LTX_API_KEY" \
-H "Content-Type: application/json" \
-D headers.txt \
--output first-clip.mp4 \
-d '{
"prompt": "A majestic eagle soaring through clouds at sunset",
"model": "ltx-2-3-fast",
"duration": 8,
"resolution": "1920x1080"
}'A 200 here is `application/octet-stream` — raw video bytes, not JSON. The response also carries x-request-id, Content-Type, and Content-Length. Keep x-request-id; it is the handle you quote when something goes wrong.
In Python, the equivalent trap is writing .json() out of habit:
import os, requests
r = requests.post(
"https://api.ltx.io/v1/text-to-video",
headers={
"Authorization": f"Bearer {os.environ['LTX_API_KEY']}",
"Content-Type": "application/json",
},
json={
"prompt": "A majestic eagle soaring through clouds at sunset",
"model": "ltx-2-3-fast",
"duration": 8,
"resolution": "1920x1080",
},
)
r.raise_for_status()
print(r.headers.get("x-request-id"))
with open("first-clip.mp4", "wb") as f:
f.write(r.content) # bytes, not r.json()The judgment question is when sync stops being right. A synchronous request holds a connection open for the entire generation, which means your client timeout, and every proxy and load balancer between you and the API, must tolerate that whole duration. Sync is excellent for a first call, a script, a notebook, or a CLI tool where a human is waiting. It stops being excellent inside a web request handler or anywhere a dropped connection loses work you have already paid for. The Developer track opens by making that trade-off properly; today, just get bytes on disk.
If you're on the Creator track
Your path is the console at console.ltx.io — the same place your key and your credit balance live.
One honest caveat: this course's verified fact sheet documents the API contract, not the console's button labels or panel layout. Interfaces get redesigned; the contract is what is guaranteed. So rather than teach you a click path that may not match your build, this lesson teaches the four decisions the form is asking you to make — because whatever it looks like, it is asking for a prompt, a model, a duration, and a resolution. If your console does not match what you read here, the current docs are authoritative on layout.
Make those decisions deliberately for your first clip:
- Model:
ltx-2-3-fast. Cheaper per second, and your first generation is an experiment. - Duration: 8 seconds. Inside every cap, long enough to have a shape.
- Resolution:
1920x1080. - Prompt: one clear shot. Something happening, somewhere specific.
Because generate_audio defaults to true, your first clip has a soundtrack the model derived from the same prompt you wrote for the picture. Listen to it. That relationship — one prompt, two streams — is the whole subject of the next lesson.
Predict the cost first
Do this before every generation until it becomes reflex. Eight seconds at 1080p on Fast:
8 s × $0.06/s = $0.48The same shot on Pro: 8 × 0.08 = $0.64. At 4K on Pro: 8 × 0.32 = $2.56, more than five times the Fast 1080p price for the same eight seconds.
There is no listed discount for generate_audio: false — the price table is indexed by endpoint, model, and resolution, and does not mention audio. Turn audio off because you do not want audio, not because you expect a refund.
Then check the duration cap from f2 before you submit, not after the error. Generate, watch, and bring the result to f5 — where we take that prompt apart.
Ship one clip
0 / 6 stepsTwo playable MP4 files from the same prompt, one static and one with dolly_in, each with audio, and a predicted cost that matches the price table arithmetic to the cent. Developer track additionally: you captured the x-request-id header from at least one response.
Knowledge check
3 questionsPick an answer to see why it is right or wrong — including the wrong ones.
A 200 response from POST /v1/text-to-video contains what?
Which set is required on a text-to-video request?
You send no fps and no generate_audio. What do you get?