Apps API
Img2Vid apps are preconfigured generation workflows. Use the Apps API when you want to call an app by id instead of choosing a media model, mode, and model-specific options yourself.
The public app API is intentionally minimal. It returns only the app id and flat input parameters, then accepts those parameter names directly in the generation request body.
Endpoints
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/v1/apps |
List callable apps and their input parameters. |
GET |
/api/v1/apps/{app} |
Get one app's input parameters. |
POST |
/api/v1/apps/{app}/generations |
Create an asynchronous generation task from an app. |
GET |
/api/v1/apps/{app}/generations/{id} |
Query an app generation task. |
All endpoints require Authorization: Bearer $BUBLE_API_KEY.
List apps
GET /api/v1/apps
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
page |
number | No | Page number. Defaults to 1. |
limit |
number | No | Page size. Defaults to 50, max 100. |
Example request
curl "https://img2vid.net/api/v1/apps?limit=20" \
-H "Authorization: Bearer $BUBLE_API_KEY"
Response shape
{
"data": [
{
"id": "video-background-remover",
"input_parameters": [
{
"name": "source_video",
"type": "array"
},
{
"name": "output_format",
"type": "string",
"values": ["webm", "mp4"]
}
]
}
]
}
Input parameters
Each app exposes a flat list of input parameters.
| Field | Description |
|---|---|
name |
Parameter name to send in the generation request body. |
type |
JSON value type: string, number, boolean, or array. |
values |
Optional allowed value range for parameters with configured discrete values. |
For media inputs, type is array; send an array of source file URLs.
Get one app
GET /api/v1/apps/{app}
curl https://img2vid.net/api/v1/apps/video-background-remover \
-H "Authorization: Bearer $BUBLE_API_KEY"
The response uses the same data shape as a single item from GET /api/v1/apps.
Create an app generation
POST /api/v1/apps/{app}/generations
Content-Type: application/json
The request body is flat. Use only parameter names returned by /api/v1/apps; unknown fields are rejected.
Example request
curl https://img2vid.net/api/v1/apps/video-background-remover/generations \
-H "Authorization: Bearer $BUBLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"source_video": ["https://example.com/source-video.mp4"]
}'
Response shape
{
"data": {
"id": "task_id",
"status": "pending"
}
}
If an app uses video-duration billing, Img2Vid calculates the source video duration server-side from the submitted video URL. Do not send duration fields to control pricing.
Query app generation
GET /api/v1/apps/{app}/generations/{id}
curl https://img2vid.net/api/v1/apps/video-background-remover/generations/task_id \
-H "Authorization: Bearer $BUBLE_API_KEY"
Status values
| Status | Meaning |
|---|---|
pending |
The task has been accepted and is waiting to run. |
processing |
The provider is generating the output. |
success |
Generation completed successfully. |
failed |
Generation failed. Check error. |
canceled |
Generation was canceled. |
Success response example
{
"data": {
"id": "task_id",
"status": "success",
"result": {
"videos": [
{
"url": "https://..."
}
]
}
}
}
Failed response example
{
"data": {
"id": "task_id",
"status": "failed",
"error": {
"message": "Generation failed."
}
}
}
App API vs media model API
Use /api/v1/apps when you want a preconfigured workflow with simple app-level inputs. Use /api/v1/media_models and /api/v1/generations when you want to choose a specific media model, mode, and model controls directly.
SDK examples
SDK app generation methods map to POST /api/v1/apps/{app}/generations. Use only parameter names returned by list or retrieve; media parameters must receive URLs, not local file paths.
The snippets below assume you have already initialized the SDK client as shown in the Quickstart and imported the required language SDK types.
JavaScript / TypeScript
const app = await buble.apps.retrieve('video-background-remover');
console.log(app.data.input_parameters);
const task = await buble.apps.generations.create('video-background-remover', {
source_video: ['https://example.com/source.mp4'],
refine_foreground_edges: true,
subject_is_person: true,
});
const result = await buble.apps.generations.wait(
'video-background-remover',
task.data.id
);
Python
app = client.apps.retrieve("video-background-remover")
print(app["data"]["input_parameters"])
task = client.apps.generations.create(
"video-background-remover",
source_video=["https://example.com/source.mp4"],
refine_foreground_edges=True,
subject_is_person=True,
)
result = client.apps.generations.wait("video-background-remover", task["data"]["id"])
Go
app, err := client.Apps.Retrieve(ctx, "video-background-remover")
if err != nil {
return err
}
fmt.Println(app.Data.InputParameters)
task, err := client.Apps.Generations.Create(ctx, "video-background-remover", map[string]any{
"source_video": []string{"https://example.com/source.mp4"},
"refine_foreground_edges": true,
"subject_is_person": true,
})
if err != nil {
return err
}
result, err := client.Apps.Generations.Wait(ctx, "video-background-remover", task.Data.ID)
Rust
let app = client.apps().retrieve("video-background-remover").await?;
println!("{:?}", app.data.input_parameters);
let mut body = serde_json::Map::new();
body.insert(
"source_video".to_string(),
serde_json::json!(["https://example.com/source.mp4"]),
);
body.insert("refine_foreground_edges".to_string(), serde_json::json!(true));
body.insert("subject_is_person".to_string(), serde_json::json!(true));
let task = client
.apps()
.generations()
.create("video-background-remover", body)
.await?;
let result = client
.apps()
.generations()
.wait("video-background-remover", &task.data.id, WaitOptions::default())
.await?;
Swift
let app = try await client.apps.retrieve("video-background-remover")
print(app.data.inputParameters)
let task = try await client.apps.generations.create(
"video-background-remover",
body: [
"source_video": ["https://example.com/source.mp4"],
"refine_foreground_edges": true,
"subject_is_person": true
]
)
let result = try await client.apps.generations.wait(
"video-background-remover",
task.data.id
)
Dart / Flutter
final app = await client.apps.retrieve('video-background-remover');
print(app.data.inputParameters);
final task = await client.apps.generations.create('video-background-remover', {
'source_video': ['https://example.com/source.mp4'],
'refine_foreground_edges': true,
'subject_is_person': true,
});
final result = await client.apps.generations.wait(
'video-background-remover',
task.data.id,
);
Elixir
{:ok, app} = Buble.Apps.retrieve(client, "video-background-remover")
IO.inspect(app["data"]["input_parameters"])
{:ok, task} =
Buble.Apps.Generations.create(client, "video-background-remover", %{
source_video: ["https://example.com/source.mp4"],
refine_foreground_edges: true,
subject_is_person: true
})
{:ok, result} =
Buble.Apps.Generations.wait(client, "video-background-remover", task["data"]["id"])
Java
Envelope<PublicApp> app = client.apps().retrieve("video-background-remover");
System.out.println(app.getData().getInputParameters());
Envelope<AppGenerationTask> task = client.apps().generations().create(
"video-background-remover",
Map.of(
"source_video", List.of("https://example.com/source.mp4"),
"refine_foreground_edges", true,
"subject_is_person", true));
Envelope<AppGenerationTask> result = client.apps().generations().wait(
"video-background-remover",
task.getData().getId());
.NET
var app = await client.Apps.RetrieveAsync("video-background-remover");
Console.WriteLine(app!.Data!.InputParameters);
var task = await client.Apps.Generations.CreateAsync(
"video-background-remover",
new Dictionary<string, object?>
{
["source_video"] = new[] { "https://example.com/source.mp4" },
["refine_foreground_edges"] = true,
["subject_is_person"] = true
});
var result = await client.Apps.Generations.WaitAsync(
"video-background-remover",
task!.Data!.Id!);
PHP
$app = $client->apps()->retrieve('video-background-remover');
var_dump($app['data']['input_parameters']);
$task = $client->apps()->generations()->create('video-background-remover', [
'source_video' => ['https://example.com/source.mp4'],
'refine_foreground_edges' => true,
'subject_is_person' => true,
]);
$result = $client->apps()->generations()->wait(
'video-background-remover',
$task['data']['id']
);
Ruby
app = client.apps.retrieve("video-background-remover")
puts app.dig("data", "input_parameters")
task = client.apps.generations.create("video-background-remover", {
"source_video" => ["https://example.com/source.mp4"],
"refine_foreground_edges" => true,
"subject_is_person" => true
})
result = client.apps.generations.wait("video-background-remover", task.dig("data", "id"))