Media Generation
Generate Video
Generate video from text prompts (asynchronous).
POST
/
api
/
v1
/
video
Generate Video
curl --request POST \
--url https://api.example.com/api/v1/video \
--header 'Content-Type: application/json' \
--data '
{
"prompt": "<string>",
"duration": "<string>",
"style": "<string>"
}
'import requests
url = "https://api.example.com/api/v1/video"
payload = {
"prompt": "<string>",
"duration": "<string>",
"style": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({prompt: '<string>', duration: '<string>', style: '<string>'})
};
fetch('https://api.example.com/api/v1/video', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/v1/video",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'prompt' => '<string>',
'duration' => '<string>',
'style' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/v1/video"
payload := strings.NewReader("{\n \"prompt\": \"<string>\",\n \"duration\": \"<string>\",\n \"style\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/api/v1/video")
.header("Content-Type", "application/json")
.body("{\n \"prompt\": \"<string>\",\n \"duration\": \"<string>\",\n \"style\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/video")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"prompt\": \"<string>\",\n \"duration\": \"<string>\",\n \"style\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"job_id": "<string>",
"status": "<string>",
"created": "<string>",
"poll_url": "<string>"
}Generate video from a text prompt. This is an asynchronous endpoint — it returns a job ID immediately (HTTP 202) and the video is generated in the background.
Video generation is async. Poll the job status with Get Job Status or use
theo.waitForJob() in the SDK.AI-disclosure watermark. Every video returned from Theo carries a small, semi-transparent Theo logo in the bottom-right corner. This is a provenance signal that identifies the clip as AI-generated and is always applied (regardless of any branding preference). Expect +2–15 seconds of re-encode latency per clip.
Authentication
Requires a Bearer token. See Authentication.Request Body
string
required
Text description of the video to generate.
string
Target video duration (e.g.,
"5s", "10s", "15s").string
Visual style (e.g.,
"cinematic", "animation", "timelapse").Request Examples
curl -X POST https://www.hitheo.ai/api/v1/video \
-H "Authorization: Bearer $THEO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A 5-second animation of a rocket launch",
"duration": "5s",
"style": "cinematic"
}'
const job = await theo.video({
prompt: "A 5-second animation of a rocket launch",
duration: "5s",
style: "cinematic",
});
// Poll until complete
const result = await theo.waitForJob(job.job_id);
console.log(result.result); // Video URL
Response (HTTP 202)
string
Unique video request ID (prefixed
vid_).string
Job ID for polling status.
string
Always
"queued" on creation.string
ISO 8601 timestamp.
string
Relative URL to poll for job status (e.g.,
/api/v1/jobs/{job_id}).Example Response
{
"id": "vid_abc123",
"job_id": "job_xyz789",
"status": "queued",
"created": "2026-04-10T12:00:00Z",
"poll_url": "/api/v1/jobs/job_xyz789"
}
Polling for Results
Use the Get Job Status endpoint to check progress. Whenstatus is "completed", the result field contains the video URL.
curl https://www.hitheo.ai/api/v1/jobs/job_xyz789 \
-H "Authorization: Bearer $THEO_API_KEY"
Errors
| Status | Code | Description |
|---|---|---|
| 400 | missing_prompt | prompt is required |
| 401 | invalid_api_key | Missing or invalid API key |
| 503 | queue_unavailable | Video generation queue is not available — retry later |
Was this page helpful?
Generate Video
curl --request POST \
--url https://api.example.com/api/v1/video \
--header 'Content-Type: application/json' \
--data '
{
"prompt": "<string>",
"duration": "<string>",
"style": "<string>"
}
'import requests
url = "https://api.example.com/api/v1/video"
payload = {
"prompt": "<string>",
"duration": "<string>",
"style": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({prompt: '<string>', duration: '<string>', style: '<string>'})
};
fetch('https://api.example.com/api/v1/video', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/v1/video",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'prompt' => '<string>',
'duration' => '<string>',
'style' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/v1/video"
payload := strings.NewReader("{\n \"prompt\": \"<string>\",\n \"duration\": \"<string>\",\n \"style\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/api/v1/video")
.header("Content-Type", "application/json")
.body("{\n \"prompt\": \"<string>\",\n \"duration\": \"<string>\",\n \"style\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/video")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"prompt\": \"<string>\",\n \"duration\": \"<string>\",\n \"style\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"job_id": "<string>",
"status": "<string>",
"created": "<string>",
"poll_url": "<string>"
}