POST /v1/videos/generations
curl --request POST \
--url https://api.geekhub.mx/v1/videos/generations \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"prompt": "<string>",
"duration": 123,
"aspect_ratio": "<string>"
}
'import requests
url = "https://api.geekhub.mx/v1/videos/generations"
payload = {
"model": "<string>",
"prompt": "<string>",
"duration": 123,
"aspect_ratio": "<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({model: '<string>', prompt: '<string>', duration: 123, aspect_ratio: '<string>'})
};
fetch('https://api.geekhub.mx/v1/videos/generations', 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.geekhub.mx/v1/videos/generations",
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([
'model' => '<string>',
'prompt' => '<string>',
'duration' => 123,
'aspect_ratio' => '<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.geekhub.mx/v1/videos/generations"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"duration\": 123,\n \"aspect_ratio\": \"<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.geekhub.mx/v1/videos/generations")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"duration\": 123,\n \"aspect_ratio\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.geekhub.mx/v1/videos/generations")
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 \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"duration\": 123,\n \"aspect_ratio\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "<string>",
"model": "<string>"
}Video
POST /v1/videos/generations
Crea un job de generación de video (async)
POST
/
v1
/
videos
/
generations
POST /v1/videos/generations
curl --request POST \
--url https://api.geekhub.mx/v1/videos/generations \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"prompt": "<string>",
"duration": 123,
"aspect_ratio": "<string>"
}
'import requests
url = "https://api.geekhub.mx/v1/videos/generations"
payload = {
"model": "<string>",
"prompt": "<string>",
"duration": 123,
"aspect_ratio": "<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({model: '<string>', prompt: '<string>', duration: 123, aspect_ratio: '<string>'})
};
fetch('https://api.geekhub.mx/v1/videos/generations', 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.geekhub.mx/v1/videos/generations",
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([
'model' => '<string>',
'prompt' => '<string>',
'duration' => 123,
'aspect_ratio' => '<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.geekhub.mx/v1/videos/generations"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"duration\": 123,\n \"aspect_ratio\": \"<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.geekhub.mx/v1/videos/generations")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"duration\": 123,\n \"aspect_ratio\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.geekhub.mx/v1/videos/generations")
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 \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"duration\": 123,\n \"aspect_ratio\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "<string>",
"model": "<string>"
}Request body
string
required
El ID namespaced del modelo, ej.
fal/kling-3-pro. Ver Modelos video.string
required
Descripción del video. Máximo 4000 caracteres.
integer
Duración en segundos. Si no la mandas, usamos el default del modelo. Cap por modelo (ver catálogo).
string
Ratio del video. Ejemplos:
16:9, 9:16, 1:1, 4:5. Soporte depende del modelo.Response (inmediata, ~100ms)
{
"id": "e8c96506-72a1-429f-a7ed-4bb0a42541be",
"object": "video.job",
"status": "processing",
"model": "fal/kling-3-pro",
"prompt": "un astronauta surfeando una ola gigante de salsa verde",
"video_url": null,
"duration": 5,
"error": null,
"created": 1782415166,
"completed": null
}
string
El job_id. Úsalo para polling.
string
Generalmente
processing. Raro pero posible failed si la submission al provider explotó.string
El model id que pediste.
Ejemplos
job = client.post("/videos/generations", body={
"model": "fal/kling-3-pro",
"prompt": "Un astronauta surfeando una ola gigante de salsa verde, cinematográfico",
"duration": 5,
"aspect_ratio": "16:9",
})
print(job["id"])
job = client.post("/videos/generations", body={
"model": "google/veo-3.1",
"prompt": "Un colibrí bebiendo de una flor de cempasúchil al amanecer, foley naturalista",
"duration": 8,
})
curl -X POST https://api.geekhub.mx/v1/videos/generations \
-H "Authorization: Bearer ghub_sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"model": "fal/kling-3-pro",
"prompt": "Un astronauta surfeando una ola gigante de salsa verde",
"duration": 5,
"aspect_ratio": "16:9"
}'
⚠️ Sobre el costo
Al crear el job NO se cobra todavía. El cobro ocurre cuando el job transita acompleted. Si falla, no hay cargo.
Cap de seguridad: tu saldo se valida al submit — si está ≤ 0 te devolvemos 402 insufficient_balance antes de crear el job.
Antes de mandar muchos jobs en paralelo, calcula tu cost máximo:
duration × precio_modelo × markup × FX. Por ejemplo 10 videos Kling 5s = 10 × 5 × $0.04 × 1.05 × 20 = $42 MXN.Siguiente paso
GET /v1/videos/{id}
Polea el estado del job hasta que llegue a
completed.⌘I