AI Video
Text-to-video generation with status polling and cancellation.
1. Overview
https://api.infrai.cc/v1/videoAuthorization: Bearer $INFRAI_API_KEY# Call any /v1/video capability over raw HTTP — no SDK to install.
# curl:
curl https://api.infrai.cc/v1/video/... \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json"2. Methods (7)
2.1video.generate
Start a text-to-video generation job.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
prompt | string | Required | Text description of the desired video. |
reference_image | string | Optional | Optional reference image URL. |
duration_seconds | number | Optional | Clip duration in seconds.1–60default: 5 |
aspect_ratio | "16:9" | "9:16" | "1:1" | Optional | Aspect ratio.default: "16:9" |
resolution | "720p" | "1080p" | "4k" | Optional | Output resolution (720p/1080p/4k); gated per vendor.default: "720p" |
model | string | Optional | Explicit model id for video generation (e.g. "kling-v2", "cogvideox"). |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
VideoJob { job_id, state, video_url?, thumbnail_url?, error? }| Name | Type | Description |
|---|---|---|
job_id | string | Unique identifier for this async jobpattern: ^vid_[A-Za-z0-9]{20,}$ |
state | "queued" | "running" | "succeeded" | "failed" | "cancelled" | "expired" | Current lifecycle state of this resource |
model | string | Model identifier to use for generation |
vendor | string | Vendor that handled or will handle this request |
prompt | string | Text prompt for content generation |
duration_seconds | integer | Duration of generated video in seconds≥ 1 |
aspect_ratio | "16:9" | "9:16" | "1:1" | "4:3" | "3:4" | "21:9" | Aspect ratio for generated images or video (e.g. 16:9) |
video_url | string | null | URL to the generated video file |
thumbnail_url | string | null | URL to the video thumbnail image |
cost_usd | number | null | Cost of this operation in USD≥ 0 |
created_at | string | ISO 8601 timestamp when this resource was createdformat: date-time |
finished_at | string | null | ISO 8601 timestamp when the job finishedformat: date-time |
retention_days | integer | null | Number of days to retain this resource≥ 0 |
parent_job_id | string | null | Source job this one was derived from via video.extend / video.upscale / webhook re-run; null for original generate jobs.pattern: ^vid_[A-Za-z0-9]{20,}$ |
error | object | Vendor/gateway error detail; present only when state is failed. |
error.code | string | Stable identifier from registry.yaml. |
error.http_status | integer | HTTP status code of the webhook delivery attempt400–599 |
error.message | string | Human-readable hint. |
error.docs_url | string | Documentation URL for this error codeformat: uri |
error.code_detail | string | Sub-classification (e.g. wallet cap reason). |
error.retryable | boolean | Whether the error is retryable |
error.retry_after_ms | integer | Suggested retry delay in milliseconds≥ 0 |
error.param | string | Which parameter failed validation, if applicable. |
error.trace_id | string | Distributed tracing identifier |
error.request_id | string | Server-assigned request identifier for tracing |
metadata | object | Cost/vendor/model disclosure for this generation (cost-transparency contract surface); present once a vendor has been selected. |
metadata.request_id | string | UUID v7. |
metadata.trace_id | string | Distributed tracing identifier |
metadata.timestamp | string | Unix timestamp of the data pointformat: date-time |
metadata.latency_ms | integer | Latency of the operation in milliseconds≥ 0 |
metadata.entry_form | any | Entry point format (rest, mcp, sdk) |
metadata.cost_usd | number | Cost of this operation in USD≥ 0 |
metadata.cost_cny | number | Cost in CNY for this request≥ 0 |
metadata.vendor | string | Adapter name; references VendorRegistry. |
metadata.vendor_region | "china" | "western" | Vendor region where the request was processed |
metadata.markup_pct | 0 | 0.05 | Markup percentage applied on top of vendor cost |
metadata.cache_layer | "none" | "l1_hit" | "l1_miss" | "l2_hit" | "batch" | Cache layer that served the response |
metadata.failover_info | object | Failover details when a different vendor was used |
metadata.failover_info.primary_vendor | string | Primary vendor that was attempted |
metadata.failover_info.actual_vendor | string | Vendor that actually handled the request (after failover) |
metadata.failover_info.primary_model | string | Primary model that was attempted |
metadata.failover_info.actual_model | string | Model that actually handled the request (after failover) |
metadata.failover_info.cost_at_primary | number | Cost at the primary vendor in USD≥ 0 |
metadata.failover_info.cost_at_actual | number | Cost at the actual vendor in USD≥ 0 |
metadata.failover_info.cost_multiplier | number | Cost multiplier due to failover≥ 0 |
metadata.failover_info.failover_reason | "VENDOR_TIMEOUT" | "VENDOR_DOWN" | "RATE_LIMIT_VENDOR" | "VENDOR_AUTH_ERROR" | Reason for the failover |
metadata.failover_info.fallback_chain_depth | integer | Depth of the failover chain traversed≥ 1 |
metadata.edge_pop | string | Geographic PoP that served this request. |
metadata.worker_id | string | Worker process identifier that handled the request |
metadata.idempotent_replay | boolean | true when this write was served from an earlier idempotent result (Idempotency-Key replay). Gateway-set; SDKs MUST read it from metadata, not a header. |
Example
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/video/generate \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "hello"}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/video/generate",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'prompt': 'hello'},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/generate",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"prompt": "hello"}),
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/generate",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"prompt": "hello"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := []byte(`{"prompt": "hello"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/video/generate", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/generate"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"prompt\": \"hello\"}"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("POST"), "https://api.infrai.cc/v1/video/generate");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"prompt\": \"hello\"}", System.Text.Encoding.UTF8, "application/json");
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/generate");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"prompt\": \"hello\"}");
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/generate")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{"prompt": "hello"}'
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.post("https://api.infrai.cc/v1/video/generate")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"prompt": "hello"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.2video.status
Poll the status of a video job.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | The job identifier. |
Returns
VideoJob| Name | Type | Description |
|---|---|---|
job_id | string | Unique identifier for this async jobpattern: ^vid_[A-Za-z0-9]{20,}$ |
state | "queued" | "running" | "succeeded" | "failed" | "cancelled" | "expired" | Current lifecycle state of this resource |
progress_pct | integer | null | Progress of the async operation as a percentage (0-100)0–100 |
eta_seconds | integer | null | Estimated seconds until completion≥ 0 |
current_step | string | null | Description of the current processing step |
Example
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/video/status/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/status/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/status/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/status/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/video/status/ID", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/status/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/video/status/ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/status/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/status/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/video/status/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.3video.cancel
Cancel a running video job.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | The job identifier. |
Returns
{ ok: boolean }| Name | Type | Description |
|---|---|---|
job_id | string | Unique identifier for this async jobpattern: ^vid_[A-Za-z0-9]{20,}$ |
state | "queued" | "running" | "succeeded" | "failed" | "cancelled" | "expired" | Current lifecycle state of this resource |
model | string | Model identifier to use for generation |
vendor | string | Vendor that handled or will handle this request |
prompt | string | Text prompt for content generation |
duration_seconds | integer | Duration of generated video in seconds≥ 1 |
aspect_ratio | "16:9" | "9:16" | "1:1" | "4:3" | "3:4" | "21:9" | Aspect ratio for generated images or video (e.g. 16:9) |
video_url | string | null | URL to the generated video file |
thumbnail_url | string | null | URL to the video thumbnail image |
cost_usd | number | null | Cost of this operation in USD≥ 0 |
created_at | string | ISO 8601 timestamp when this resource was createdformat: date-time |
finished_at | string | null | ISO 8601 timestamp when the job finishedformat: date-time |
retention_days | integer | null | Number of days to retain this resource≥ 0 |
parent_job_id | string | null | Source job this one was derived from via video.extend / video.upscale / webhook re-run; null for original generate jobs.pattern: ^vid_[A-Za-z0-9]{20,}$ |
error | object | Vendor/gateway error detail; present only when state is failed. |
error.code | string | Stable identifier from registry.yaml. |
error.http_status | integer | HTTP status code of the webhook delivery attempt400–599 |
error.message | string | Human-readable hint. |
error.docs_url | string | Documentation URL for this error codeformat: uri |
error.code_detail | string | Sub-classification (e.g. wallet cap reason). |
error.retryable | boolean | Whether the error is retryable |
error.retry_after_ms | integer | Suggested retry delay in milliseconds≥ 0 |
error.param | string | Which parameter failed validation, if applicable. |
error.trace_id | string | Distributed tracing identifier |
error.request_id | string | Server-assigned request identifier for tracing |
metadata | object | Cost/vendor/model disclosure for this generation (cost-transparency contract surface); present once a vendor has been selected. |
metadata.request_id | string | UUID v7. |
metadata.trace_id | string | Distributed tracing identifier |
metadata.timestamp | string | Unix timestamp of the data pointformat: date-time |
metadata.latency_ms | integer | Latency of the operation in milliseconds≥ 0 |
metadata.entry_form | any | Entry point format (rest, mcp, sdk) |
metadata.cost_usd | number | Cost of this operation in USD≥ 0 |
metadata.cost_cny | number | Cost in CNY for this request≥ 0 |
metadata.vendor | string | Adapter name; references VendorRegistry. |
metadata.vendor_region | "china" | "western" | Vendor region where the request was processed |
metadata.markup_pct | 0 | 0.05 | Markup percentage applied on top of vendor cost |
metadata.cache_layer | "none" | "l1_hit" | "l1_miss" | "l2_hit" | "batch" | Cache layer that served the response |
metadata.failover_info | object | Failover details when a different vendor was used |
metadata.failover_info.primary_vendor | string | Primary vendor that was attempted |
metadata.failover_info.actual_vendor | string | Vendor that actually handled the request (after failover) |
metadata.failover_info.primary_model | string | Primary model that was attempted |
metadata.failover_info.actual_model | string | Model that actually handled the request (after failover) |
metadata.failover_info.cost_at_primary | number | Cost at the primary vendor in USD≥ 0 |
metadata.failover_info.cost_at_actual | number | Cost at the actual vendor in USD≥ 0 |
metadata.failover_info.cost_multiplier | number | Cost multiplier due to failover≥ 0 |
metadata.failover_info.failover_reason | "VENDOR_TIMEOUT" | "VENDOR_DOWN" | "RATE_LIMIT_VENDOR" | "VENDOR_AUTH_ERROR" | Reason for the failover |
metadata.failover_info.fallback_chain_depth | integer | Depth of the failover chain traversed≥ 1 |
metadata.edge_pop | string | Geographic PoP that served this request. |
metadata.worker_id | string | Worker process identifier that handled the request |
metadata.idempotent_replay | boolean | true when this write was served from an earlier idempotent result (Idempotency-Key replay). Gateway-set; SDKs MUST read it from metadata, not a header. |
Example
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/video/cancel/ID \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"job_id": "sample"}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/video/cancel/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'job_id': 'sample'},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/cancel/ID",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"job_id": "sample"}),
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/cancel/ID",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"job_id": "sample"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := []byte(`{"job_id": "sample"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/video/cancel/ID", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/cancel/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"job_id\": \"sample\"}"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("POST"), "https://api.infrai.cc/v1/video/cancel/ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"job_id\": \"sample\"}", System.Text.Encoding.UTF8, "application/json");
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/cancel/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"job_id\": \"sample\"}");
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/cancel/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{"job_id": "sample"}'
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.post("https://api.infrai.cc/v1/video/cancel/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"job_id": "sample"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.4video.get
获取视频任务的完整详情(状态、视频地址、时长、分辨率、厂商、模型等)。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | The job identifier. |
Returns
VideoJob { job_id, state, video_url?, thumbnail_url?, duration_seconds, resolution, vendor, model, error? }| Name | Type | Description |
|---|---|---|
job_id | string | Unique identifier for this async jobpattern: ^vid_[A-Za-z0-9]{20,}$ |
state | "queued" | "running" | "succeeded" | "failed" | "cancelled" | "expired" | Current lifecycle state of this resource |
model | string | Model identifier to use for generation |
vendor | string | Vendor that handled or will handle this request |
prompt | string | Text prompt for content generation |
duration_seconds | integer | Duration of generated video in seconds≥ 1 |
aspect_ratio | "16:9" | "9:16" | "1:1" | "4:3" | "3:4" | "21:9" | Aspect ratio for generated images or video (e.g. 16:9) |
video_url | string | null | URL to the generated video file |
thumbnail_url | string | null | URL to the video thumbnail image |
cost_usd | number | null | Cost of this operation in USD≥ 0 |
created_at | string | ISO 8601 timestamp when this resource was createdformat: date-time |
finished_at | string | null | ISO 8601 timestamp when the job finishedformat: date-time |
retention_days | integer | null | Number of days to retain this resource≥ 0 |
parent_job_id | string | null | Source job this one was derived from via video.extend / video.upscale / webhook re-run; null for original generate jobs.pattern: ^vid_[A-Za-z0-9]{20,}$ |
error | object | Vendor/gateway error detail; present only when state is failed. |
error.code | string | Stable identifier from registry.yaml. |
error.http_status | integer | HTTP status code of the webhook delivery attempt400–599 |
error.message | string | Human-readable hint. |
error.docs_url | string | Documentation URL for this error codeformat: uri |
error.code_detail | string | Sub-classification (e.g. wallet cap reason). |
error.retryable | boolean | Whether the error is retryable |
error.retry_after_ms | integer | Suggested retry delay in milliseconds≥ 0 |
error.param | string | Which parameter failed validation, if applicable. |
error.trace_id | string | Distributed tracing identifier |
error.request_id | string | Server-assigned request identifier for tracing |
metadata | object | Cost/vendor/model disclosure for this generation (cost-transparency contract surface); present once a vendor has been selected. |
metadata.request_id | string | UUID v7. |
metadata.trace_id | string | Distributed tracing identifier |
metadata.timestamp | string | Unix timestamp of the data pointformat: date-time |
metadata.latency_ms | integer | Latency of the operation in milliseconds≥ 0 |
metadata.entry_form | any | Entry point format (rest, mcp, sdk) |
metadata.cost_usd | number | Cost of this operation in USD≥ 0 |
metadata.cost_cny | number | Cost in CNY for this request≥ 0 |
metadata.vendor | string | Adapter name; references VendorRegistry. |
metadata.vendor_region | "china" | "western" | Vendor region where the request was processed |
metadata.markup_pct | 0 | 0.05 | Markup percentage applied on top of vendor cost |
metadata.cache_layer | "none" | "l1_hit" | "l1_miss" | "l2_hit" | "batch" | Cache layer that served the response |
metadata.failover_info | object | Failover details when a different vendor was used |
metadata.failover_info.primary_vendor | string | Primary vendor that was attempted |
metadata.failover_info.actual_vendor | string | Vendor that actually handled the request (after failover) |
metadata.failover_info.primary_model | string | Primary model that was attempted |
metadata.failover_info.actual_model | string | Model that actually handled the request (after failover) |
metadata.failover_info.cost_at_primary | number | Cost at the primary vendor in USD≥ 0 |
metadata.failover_info.cost_at_actual | number | Cost at the actual vendor in USD≥ 0 |
metadata.failover_info.cost_multiplier | number | Cost multiplier due to failover≥ 0 |
metadata.failover_info.failover_reason | "VENDOR_TIMEOUT" | "VENDOR_DOWN" | "RATE_LIMIT_VENDOR" | "VENDOR_AUTH_ERROR" | Reason for the failover |
metadata.failover_info.fallback_chain_depth | integer | Depth of the failover chain traversed≥ 1 |
metadata.edge_pop | string | Geographic PoP that served this request. |
metadata.worker_id | string | Worker process identifier that handled the request |
metadata.idempotent_replay | boolean | true when this write was served from an earlier idempotent result (Idempotency-Key replay). Gateway-set; SDKs MUST read it from metadata, not a header. |
Example
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/video/get/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/get/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/get/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/get/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/video/get/ID", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/get/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/video/get/ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/get/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/get/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/video/get/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.5video.delete
删除指定视频任务及其产物(幂等写)。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | The job identifier. |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
{ ok: boolean }| Name | Type | Description |
|---|---|---|
job_id | string | null | The job affected; null for bulk ops (delete_all).pattern: ^vid_[A-Za-z0-9]{20,}$ |
Example
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X DELETE https://api.infrai.cc/v1/video/delete/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.delete(
"https://api.infrai.cc/v1/video/delete/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/delete/ID",
{
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/delete/ID",
{
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("DELETE", "https://api.infrai.cc/v1/video/delete/ID", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/delete/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("DELETE", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("DELETE"), "https://api.infrai.cc/v1/video/delete/ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/delete/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/delete/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Delete.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.delete("https://api.infrai.cc/v1/video/delete/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.6video.download_url
为指定视频任务签发带过期时间的临时下载链接。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | The job identifier. |
Returns
{ url: string, expires_at: string }| Name | Type | Description |
|---|---|---|
job_id | string | Unique identifier for this async jobpattern: ^vid_[A-Za-z0-9]{20,}$ |
url | string | Signed, time-limited download URL hosted by Infrai.format: uri |
expires_at | string | ISO 8601 timestamp when this resource or token expiresformat: date-time |
size_bytes | integer | null | Size of the resource in bytes≥ 0 |
content_type | string | null | MIME type of the object |
Example
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/video/download_url/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/download_url/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/download_url/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/download_url/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/video/download_url/ID", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/download_url/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/video/download_url/ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/download_url/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/download_url/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/video/download_url/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.7video.capabilities
查询各视频厂商支持的模型、分辨率、最大时长及扩展/超分能力。
Returns
VideoCapabilities { vendors: Array<{ vendor, models, resolutions, max_duration_seconds, supports_extend, supports_upscale }> }| Name | Type | Description |
|---|---|---|
models | object[] | Served video models, one per priced (vendor, model) row. |
models[].vendor | string | - |
models[].model | string | - |
models[].region | string | null | - |
models[].max_seconds | integer | null | Max generation duration the vendor adapter enforces (DURATION_EXCEEDED above this); null if the adapter is absent.≥ 1 |
models[].image_to_video | boolean | null | Whether the vendor supports image-to-video; null if the adapter is absent. |
resolutions | ("720p" | "1080p" | "4k")[] | Supported resolution keys (also the keys of resolution_multiplier). |
resolution_multiplier | object | Per-resolution cost-axis multiplier (e.g. 720p=1.0, 1080p=2.0, 4k=4.0). |
Example
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/video/capabilities \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/capabilities",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/capabilities",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/capabilities",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/video/capabilities", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/capabilities"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/video/capabilities");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/capabilities");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/capabilities")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/video/capabilities")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}Advanced: pin a vendor
By default infrai routes each call to the best available provider — you do not pick a vendor. As an escape hatch, this capability accepts an optional vendor parameter to pin one specific provider. Every live vendor for this capability is available in real time from the discovery endpoint for the capability id — see the discovery API.
GET /v1/discovery/{capability}video.generate
3. All capabilities
Every routed capability in this module — the complete public REST contract. The methods above are the guided walkthrough; this index is the full reference.
video.cancelPOST /v1/video/cancel/{id}Cancel an in-progress video generation job.
Parameters (3)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
job_id | string | Required | Id of the video job to cancel. |
idempotency_key | string | null | Optional | Client-provided idempotency key; prevents duplicate execution on retry |
video.capabilitiesGET /v1/video/capabilitiesQuery each video provider's supported models, resolutions, max duration, and extend/upscale capabilities.
No request parameters.
video.deleteDELETE /v1/video/delete/{id}Delete a video job and its artifacts (idempotent write).
Parameters (1)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
video.download_urlGET /v1/video/download_url/{id}Issue a time-limited, expiring download URL for a video job's output.
Parameters (1)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
video.generatePOST /v1/video/generateGenerate a video from a text or image prompt asynchronously (idempotent).
Parameters (12)
| Name | Type | Required | Description |
|---|---|---|---|
prompt | string | Required | Text prompt for content generation |
model | string | null | Optional | Model selector. A specific video model id (e.g. 'wan-t2v'), OR a routing MODE: 'auto' (default, balanced value), 'cheapest' (lowest USD/s), 'smartest' (flagship). Null = auto. |
resolution | "720p" | "1080p" | "4k" | Optional | Output resolution spec axis. Gated per-vendor. (SSOT: enums/VideoResolution)default: "720p" |
duration_seconds | integer | Optional | Duration of generated video in seconds1–60default: 5 |
aspect_ratio | "16:9" | "9:16" | "1:1" | "4:3" | "3:4" | "21:9" | Optional | Aspect ratio for generated images or video (e.g. 16:9)default: "16:9" |
seed | integer | null | Optional | Random seed for deterministic generation |
negative_prompt | string | null | Optional | Negative prompt for excluding unwanted content |
reference_image | string | null | Optional | URL or base64 for image-to-video. |
vendor | string | null | Optional | Vendor that handled or will handle this request |
webhook_url | string | null | Optional | Optional callback URL; declares an async delivery target at submit time (events from VideoEventType). Equivalent to a video.webhook.subscribe for this job.format: uri |
idempotency_key | string | null | Optional | Client-provided idempotency key; prevents duplicate execution on retry |
store | boolean | Optional | Opt in to RETAIN the produced asset/record in Infrai's own store (default false = stateless passthrough: process, return inline, keep nothing). When true, Infrai persists the asset, bills a self-hosted storage line item and applies a retention TTL — and only then do the *.list/get/delete read caps see it.default: false |
video.getGET /v1/video/get/{id}Retrieve a video job's full details (status, video URL, duration, resolution, provider, model).
Parameters (1)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
video.statusGET /v1/video/status/{id}Query a video generation job's status and output URL.
Parameters (1)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
4. End-to-end example
A production-style walkthrough of this module: configure once, then run the flow. It exercises most of the module's APIs.
A copy-paste-runnable single-file Python program (stdlib only, no SDK): set your INFRAI_API_KEY, run it, and walk this module's core flow with REAL billed calls — later steps reuse real fields returned by earlier ones. The 12-line helper is the entire integration.
#!/usr/bin/env python3
"""Infrai · ai-video — runnable real-app example (single file, zero deps).
Copy this file, set your key, run it: every step is a REAL call to
api.infrai.cc, billed at the real (tiny) per-call price, printing the
live JSON response. Get a key at https://infrai.cc/login (Google/
GitHub sign-in grants $2 free credit); add funds at
https://infrai.cc/billing. No SDK — the 12-line helper below is the
entire integration."""
import json
import os
from urllib import error, request
KEY = os.environ.get("INFRAI_API_KEY") or "ifr_..." # <- your key
BASE = "https://api.infrai.cc"
# Same raw HTTPS POST/GET as every per-method example on this page —
# wrapped once for reuse. There is nothing else to it: no SDK.
def infrai(method, path, body=None):
req = request.Request(
BASE + path, method=method,
data=json.dumps(body).encode() if body is not None else None,
headers={"Authorization": f"Bearer {KEY}",
"Content-Type": "application/json"})
try:
with request.urlopen(req, timeout=60) as r:
return json.loads(r.read())
except error.HTTPError as e:
return json.loads(e.read())
def show(label, resp):
print(f"\n== {label} ==")
print(json.dumps(resp, indent=2, ensure_ascii=False))
return resp
# 1) video.generate — POST /v1/video/generate · Generate a video from a text or image prompt asynchronously (idempotent). # NOTE: non-trivial real cost
r1 = show("video.generate", infrai("POST", "/v1/video/generate", {"prompt":"a timelapse of a city skyline at dusk","resolution":"1080p","duration_seconds":5}))
# 2) video.status — GET /v1/video/status/{id} · Query a video generation job's status and output URL.
id_2 = (r1.get("data") or {}).get("job_id") or ""
r2 = show("video.status", infrai("GET", f"/v1/video/status/{id_2}"))
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."# 1) Auth: every call is a raw HTTPS request to the Infrai gateway carrying
# only your project key. No SDK, no install.
# Get your key: sign in with Google/GitHub at https://infrai.cc/login for a
# project key + $2 free credit (email sign-in starts at $0). On 402
# INSUFFICIENT_CREDIT, add funds at https://infrai.cc/billing (or POST
# /v1/account/topup and open the returned checkout_url).
export INFRAI_API_KEY="ifr_..." # from https://infrai.cc/login
# 2) video.generate
curl -X POST https://api.infrai.cc/v1/video/generate \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "hello"}'
# 3) video.status
curl -X GET https://api.infrai.cc/v1/video/status/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 4) video.cancel
curl -X POST https://api.infrai.cc/v1/video/cancel/ID \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"job_id": "sample"}'
# 5) video.get
curl -X GET https://api.infrai.cc/v1/video/get/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 6) video.delete
curl -X DELETE https://api.infrai.cc/v1/video/delete/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 7) video.download_url
curl -X GET https://api.infrai.cc/v1/video/download_url/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 1) Auth: every call is a raw HTTPS request carrying only your project key.
# No SDK to install — just the `requests` library.
import os, requests
BASE = "https://api.infrai.cc"
HEADERS = {
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
"Content-Type": "application/json",
}
# 2) video.generate
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/video/generate",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'prompt': 'hello'},
)
resp.raise_for_status()
print(resp.json())
# 3) video.status
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/status/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 4) video.cancel
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/video/cancel/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'job_id': 'sample'},
)
resp.raise_for_status()
print(resp.json())
# 5) video.get
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/get/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 6) video.delete
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.delete(
"https://api.infrai.cc/v1/video/delete/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 7) video.download_url
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/download_url/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
// 1) Auth: every call is a raw HTTPS request carrying only your project key.
// No SDK to install — just the built-in fetch().
const BASE = "https://api.infrai.cc";
const HEADERS = {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
};
// 2) video.generate
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/generate",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"prompt": "hello"}),
},
);
console.log(await resp.json());
// 3) video.status
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/status/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 4) video.cancel
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/cancel/ID",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"job_id": "sample"}),
},
);
console.log(await resp.json());
// 5) video.get
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/get/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 6) video.delete
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/delete/ID",
{
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 7) video.download_url
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/download_url/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 1) Auth: every call is a raw HTTPS request carrying only your project key.
// No SDK to install — just the built-in fetch(), typed.
const BASE = "https://api.infrai.cc";
const HEADERS: Record<string, string> = {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
};
// 2) video.generate
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/generate",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"prompt": "hello"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 3) video.status
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/status/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 4) video.cancel
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/cancel/ID",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"job_id": "sample"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 5) video.get
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/get/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 6) video.delete
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/delete/ID",
{
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 7) video.download_url
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/download_url/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);