Grok Imagine Video API: Animate a Product Image

Start with one product image, ask for a controlled camera movement, and keep the returned task ID until you have downloaded and inspected the video. Tokenhot’s documented grok-imagine-video-1-5-preview route is image-to-video: it requires one public image URL. This is not a tutorial for text-only generation or arbitrary video editing.
The workflow below separates preparation, a single submission, status queries, and downloading. Its Python implementation has offline tests, but no real product image was submitted and no model-generated video was inspected for this article. A sample request is not a quality or latency benchmark.
1. Prepare one image that the API can actually retrieve
The Tokenhot generation reference requires input.image_urls with one publicly accessible image. It lists JPEG/JPG, PNG, and WEBP, a size no greater than 20 MB, and no Base64 input.
Use a product photograph you are authorized to process. Open its direct URL without your browser’s logged-in session and check that it returns the image itself, not a gallery page, login screen, or HTML download page. Inspect its actual file type and size; the filename extension alone does not prove either. Your local browser’s access is only a preparation check, not proof the provider can retrieve it from its network.
For a first authored example, use a clearly visible product on a simple background. A prompt such as this keeps the requested movement easy to evaluate:
Create a slow, subtle camera push-in toward the product. Keep the product's shape, color, label, and background consistent. Do not add new objects or text.
This is an instruction to the model, not a promise that it will preserve the label perfectly. Product identity and text should be inspected in the result before the clip is used.
2. Keep the image-to-video fields inside input
The route uses POST https://api.tokenhot.ai/v1/video/generations with Bearer authentication. An authored request based on its documented structure is:
{
"model": "grok-imagine-video-1-5-preview",
"input": {
"image_urls": ["https://your-public-image-host.example/product.png"],
"prompt": "Create a slow camera push-in. Keep the product and its label consistent. Do not add new objects or text.",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 8
}
}
Replace the example URL with your actual direct image URL. The 16:9, 720p, and 8 settings follow the published example; they are not a verified list of all allowed settings or a measured result duration. This tutorial does not turn an example into an undocumented maximum.
The published request also includes a safety-check override. This authored request deliberately leaves that override out instead of disabling it. The read document does not establish the omitted field’s default or optionality, so this remains a live-validation point: if the route rejects omission, confirm its supported safe setting with Tokenhot rather than copying a disabling value just to make the request pass.
3. Prepare locally, then authorize a single submission
Save the complete Python companion as media_workflows.py. It uses only the standard library and was checked with Python 3.13.5. Put the motion prompt in a UTF-8 motion.txt file.
Preparation does not contact the API:
python media_workflows.py grok-request --image-url "https://your-public-image-host.example/product.png" --prompt-file motion.txt --out grok-request.json
The helper checks URL shape, not the remote file’s size, content, or reachability. Complete the image inspection above yourself. Keep private or expiring URLs out of shared logs.
Follow Quick Start for your account key, and set TOKENHOT_API_KEY in the environment. After reviewing the request and its possible charge, submit:
python media_workflows.py submit --kind grok --request grok-request.json --run runs/grok-001 --execute
The helper creates a new run directory before making one POST. It saves the received response before parsing it and writes the selected task ID into task.json. It does not retry the POST.
An existing run directory is rejected. This is a local guard against accidental repetition, not a provider idempotency guarantee. Changing the directory name can still create another billable job.
4. Query task_id—not a guessed alias
The submission example contains both id and task_id, with different placeholder strings. The Grok task-query reference specifically instructs you to query the returned task_id:
GET https://api.tokenhot.ai/v1/video/generations/{task_id}
The helper therefore requires task_id; it does not fall back to id. A submission response with status: "queued" only acknowledges the job. It is not the final video.
Run a bounded query sequence against the saved submission:
python media_workflows.py poll --submission runs/grok-001/response.json --model grok-imagine-video-1-5-preview --out runs/grok-poll-001 --attempts 12 --interval 5 --execute
Each GET response is stored separately. The helper requires a successful envelope, the matching task ID and model, and data.status: "SUCCESS" with data.result_url before creating success.json. A progress value alone does not release a download.
The Grok query page shows a success example but not a complete intermediate-state list. For that reason, the helper records other nonempty states without claiming they are the same as Veo or Kling states. It keeps querying within the selected attempt count, unless a failure reason or rejected response stops it. A non-success result never becomes a successful video just because the budget runs out.
Twelve attempts and a five-second interval are local example settings, not a model completion estimate. HTTP calls take additional time; this is not a strict total wall-clock deadline. A failed GET stops the command. To continue later, reuse the original submission and choose a new polling output directory—do not submit another generation request.
5. Download from the result host without forwarding your API key
When runs/grok-poll-001/success.json exists, inspect its data.result_url privately. Confirm the hostname belongs to the result you expect. Use the actual task ID from runs/grok-001/task.json:
python media_workflows.py download --success runs/grok-poll-001/success.json --task ACTUAL_TASK_ID --model grok-imagine-video-1-5-preview --approve-host ACTUAL_RESULT_HOST --output output/product-video.mp4 --execute
The result-host argument is a hostname, not a URL. The download command sends no Tokenhot authorization header, rejects redirects, and will not overwrite an existing output. If a redirect is required, review the destination and adapt the downloader deliberately; do not forward the API key to follow it.
The query reference says the result URL expires in approximately 24 hours. Treat it as temporary and save it promptly rather than relying on an exact expiry guarantee. A failed or expired download is not evidence that generation should be repeated.
The example checks an MP4-family file signature before saving, not every media frame. Its URL validation rejects obvious private addresses and embedded credentials but is not a DNS-rebinding defense. Use it as an operator-run local script; do not expose it as a public server that fetches arbitrary user URLs.
6. Diagnose the failed stage and inspect the finished clip
| Observation | Appropriate next action |
|---|---|
| Image cannot be retrieved or violates the input rules | Fix the actual source image and confirm whether the original task was rejected before making a deliberate new submission. |
| No usable submission response | Treat the task outcome as unknown; reconcile with account records or support before sending another POST. |
| Query contains a failure reason | Keep the task and raw response; classify the cause instead of restarting blindly. |
| Query budget ends without confirmed success | Query that same task later. Do not equate waiting with failure or completion. |
| Generation succeeds but downloading fails | Reuse the task and valid result URL; recover delivery separately from generation. |
| Video plays but changes the product or label | Reject it for that use case and revise the prompt or image deliberately; record a new version and its additional cost. |
Play the downloaded clip and compare it with the source image. Inspect the beginning, middle, and end for product shape, logo/text consistency, unexpected objects, framing, and movement. Check any audio track as well before publishing.
Keep the source image reference, exact prompt, task ID, response files, and accepted local result together. That record lets you distinguish a delivery problem from a creative-quality problem without paying for a new generation simply because a file was not saved correctly.
Prepare one public product image, submit a Grok image-to-video task, track the correct task ID, and save its result without repeating generation.


