If you want a short, sound-on video from a single line of text, grok-imagine-1.5-lite/text-to-video is the cheapest way to get there on hiapi that still reaches 1080P. It takes one prompt, returns a 1–15 second MP4 with audio already mixed in, and runs on the same unified task API as every other model on the platform. This page gives you a request you can paste and run, the exact schema (verified against the live endpoint, not copied from a spec), what a real response looks like, and the gotchas I hit while testing it.
Everything below was checked against the live API on 2026-10-21. Prices are quoted as I measured them; the pricing page is the source of truth if they change.
1. What you'll build, and what you need
Goal: send a text prompt, get back a downloadable MP4 clip with audio.
You need one thing: an hiapi API key. Create one in the dashboard and keep it server-side — it looks like sk-... and goes in an Authorization: Bearer header. There is no no-key path; every request below must be authenticated.
This model is asynchronous. You don't get the video in the POST response. You create a task, get a taskId, then poll (or use a callback) until the task finishes and exposes an output URL.
2. Minimal working example
Two steps: create the task, then poll for the result.
Create the task (curl)
curl -s -X POST "https://api.hiapi.ai/v1/tasks" \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "grok-imagine-1.5-lite/text-to-video",
"input": {
"prompt": "A red fox trots across fresh snow at dawn, breath steaming, soft morning light, gentle ambient wind. Cinematic, natural colors. No text.",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "16:9"
}
}'
Note the shape: model at the top level, everything else nested under input. Send the fields flat (no input wrapper) and the API rejects the whole body with invalid input: must be a JSON object — this is the single most common mistake.
A successful create returns a task id immediately:
{ "code": 200, "data": { "taskId": "tk-hiapi-01M5E3QKSB2TAJRDHR5Y8EQNEB" }, "message": "success" }
Poll for the result (Python)
import time, requests
BASE = "https://api.hiapi.ai/v1/tasks"
HEAD = {"Authorization": "Bearer sk-YOUR_KEY", "Content-Type": "application/json"}
def generate(prompt, duration=5, resolution="720p", aspect_ratio="16:9"):
r = requests.post(BASE, headers=HEAD, json={
"model": "grok-imagine-1.5-lite/text-to-video",
"input": {
"prompt": prompt,
"duration": duration, # integer, 1–15
"resolution": resolution, # "480p" | "720p" | "1080p"
"aspect_ratio": aspect_ratio, # see schema below
},
})
r.raise_for_status()
task_id = r.json()["data"]["taskId"]
# Poll the SAVED task_id. A single transient network error is not a failure —
# keep polling the same id rather than re-creating (re-creating bills again).
deadline = time.time() + 300
while time.time() < deadline:
try:
d = requests.get(f"{BASE}/{task_id}", headers=HEAD, timeout=30).json()
except requests.RequestException:
time.sleep(5); continue
task = d.get("data") or {}
status = task.get("status")
if status == "success":
return task["output"][0]["url"]
if status == "fail":
raise RuntimeError(task.get("error"))
time.sleep(5)
raise TimeoutError(task_id)
print(generate("A red fox trots across fresh snow at dawn, gentle ambient wind. Cinematic."))
The schema (verified live)
Fields go inside input. The schema is closed — any key it doesn't recognize returns a 400, so don't send seed, negative_prompt, or motion_mode (none exist here; all camera and motion direction is prompt wording).
| Field | Type | Required | Accepted values |
|---|---|---|---|
prompt | string | yes | free text |
duration | integer | yes | 1–15 (whole seconds; 5.5 is rejected) |
resolution | string | — | 480p, 720p, 1080p |
aspect_ratio | string | — | 16:9, 4:3, 3:2, 1:1, 2:3, 3:4, 9:16 |
There is no auto aspect ratio on this model (its image-to-video sibling has one; this text-to-video endpoint does not). Pick a ratio explicitly, or you'll get whatever the model defaults to.
Here is what a finished task actually returns:
{
"code": 200,
"data": {
"taskId": "tk-hiapi-01M5E3QKSB2TAJRDHR5Y8EQNEB",
"model": "grok-imagine-1.5-lite/text-to-video",
"status": "success",
"storage": "temp",
"output": [
{ "type": "video", "url": "https://temp.hiapi.ai/.../...-0.mp4", "expireAt": 1793153637 }
]
},
"message": "success"
}
Here's a clip this model produced (hiapi's reference output for grok-imagine-1.5-lite/text-to-video, generated from its documented example prompt — "a glass hot-air balloon drifts over terraced rice fields at sunrise"):
3. Taking it to production
Use a callback instead of polling. Polling is fine for a script; for a server, add a callback so you don't hold a request open. The platform POSTs the task detail to your URL when it reaches a terminal state:
{
"model": "grok-imagine-1.5-lite/text-to-video",
"input": { "prompt": "...", "duration": 5, "resolution": "720p", "aspect_ratio": "16:9" },
"callback": { "url": "https://your.app/hooks/hiapi", "when": "final" }
}
when only accepts "final" on this task type. Dedupe on taskId in your handler — callbacks can retry, so treat the handler as idempotent.
The output URL expires. Notice storage: "temp" and the expireAt unix timestamp — temp outputs live on temp.hiapi.ai for ~7 days, then 404. Do not store the hot link. Download the bytes the moment the task succeeds, or call the storage promote endpoint to move the artifact to permanent storage before the TTL runs out.
Cost is per second of output. Billing is driven only by duration, at the resolution you request. At test time: 480P $0.029/s, 720P $0.043/s, 1080P $0.20/s. So a 5-second 720P clip ≈ $0.215, a 5-second 1080P clip ≈ $1.00, and a 1-second 480P clip ≈ $0.029. 1080P is roughly 5× the 720P rate — reach for it only when you actually need the resolution. Current numbers live on the pricing page.
Error handling. Rejected requests come back as HTTP 400 with a precise message you can log and act on. Validation happens before any task is created, so a 400 here costs nothing. Real responses I triggered:
invalid input: duration: maximum: got 999, want 15
invalid input: duration: minimum: got 0, want 1
invalid input: duration: got number, want integer
invalid input: resolution: value must be one of '480p', '720p', '1080p'
invalid input: aspect_ratio: value must be one of '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16'
invalid input: prompt: missing required field "prompt"
invalid input: <root>: additional properties 'bogus_field' not allowed
A task that is accepted but fails later surfaces as data.status: "fail" with a data.error object on the detail endpoint — not as an HTTP error — so check status, don't rely on the HTTP code of the poll.
4. What I actually observed
I ran one real generation to confirm the end-to-end flow (not just the schema): duration: 1, resolution: "480p", aspect_ratio: "16:9".
- It is genuinely live and billable — the POST returned a
taskIdand the task completed with a real output URL. Server-side it took ~51 seconds wall-clock to render a 1-second clip; even tiny clips are not instant, so set polling deadlines generously (I use 300 s). - The task moves through intermediate states. The
statusfield cycledhandling→archiving→success. Onlysuccessandfailare terminal; don't treatarchivingas done. - 480P at 16:9 renders as 848×480 H.264.
ffprobeon the downloaded file: one H.264 video stream (848×480), plus an embedded MJPEG thumbnail stream. The 495 KB file was a valid MP4. - Audio is always baked in. The output carried an AAC audio track even though my prompt only mentioned "gentle ambient wind" — the model synthesizes matching audio and muxes it into the same MP4. There is no separate audio URL and no flag to disable it; if you need a silent clip, strip the track yourself (
ffmpeg -an).
Caveat on scope: I verified the API contract, the three error classes above, and one 480P render. I did not benchmark 720P/1080P output quality or long (15 s) durations, so I'm not making quality claims about those — only that the schema accepts them and bills by the second.
5. Lite vs. the standard Grok Imagine video API
Pick the right endpoint before you build:
grok-imagine-1.5-lite/text-to-video(this page): 480P/720P/1080P, 1–15 s (so you can make a 1- or 2-second clip), priced$0.029–$0.20/s. It's the only 1.5-generation text-to-video endpoint hiapi hosts, and the only Grok t2v tier that reaches 1080P.grok-imagine/text-to-video(older standard tier, covered in this guide): cheaper per second ($0.0114–$0.0214/s) and exposes Motion Modes, but caps at 720p and requires 6–30 s durations — you can't make a sub-6-second clip.
So "lite" here is not the cheapest option per second; it's the one that unlocks 1080P and very short clips. If you're feeding a single still image instead of text, use the same-tier grok-imagine-1.5-lite/image-to-video endpoint (identical pricing, image_urls input).
6. Related
- grok-imagine-1.5-lite text-to-video model page / playground
- Create a task — API reference
- Get task detail — API reference
- Pricing
FAQ
Do I have to poll, or is there a callback? Both work. Poll GET /v1/tasks/{taskId} for scripts; attach callback.url with when: "final" for servers. Dedupe on taskId.
Why did my request 400 with "must be a JSON object"? Your fields aren't wrapped in input. The body must be {"model": "...", "input": { ... }}.
Can I turn off the audio? Not at request time — every output includes a muxed AAC track. Remove it downstream with ffmpeg -an if you need silence.
How long is the output URL valid? It's a temp URL with an expireAt (~7 days). Download or promote to permanent storage immediately; don't hotlink it.
What's the cheapest valid request? 1 second at 480P ≈ $0.029. It's a good canary to confirm your key has balance before a batch.





