Quickstart

This guide creates a text-to-image task, then polls the result.

1. Set your API key

export BUBLE_API_KEY="sk_your_api_key"

Use API keys only on the server side. Do not expose them in browser code.

2. List available media models

curl https://img2vid.net/api/v1/media_models \
  -H "Authorization: Bearer $BUBLE_API_KEY"

Pick a media model and one of its operations[].mode values.

3. Create a text-to-image generation

curl https://img2vid.net/api/v1/generations \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/nano-banana-pro",
    "mode": "text_to_image",
    "prompt": "A premium product photo of a matte black wireless speaker on a marble table, cinematic studio lighting",
    "aspect_ratio": "1:1",
    "resolution": "1K",
    "output_format": "png"
  }'

The response contains a generation id.

4. Poll the task

curl https://img2vid.net/api/v1/generations/YOUR_GENERATION_ID \
  -H "Authorization: Bearer $BUBLE_API_KEY"

Continue polling until data.status becomes success or failed.

5. Use uploaded files when needed

For image-to-image or image-to-video workflows, upload the source file first:

curl https://img2vid.net/api/v1/files \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -F "file=@./reference.png" \
  -F "file_type=image" \
  -F "model=google/nano-banana-pro" \
  -F "mode=image_to_image"

Then pass the returned data.url to image_urls, start_frame, or another input field supported by the selected mode.

6. Use an official SDK

The SDKs wrap the stable public API contract: model/app discovery, file upload, asynchronous generation creation, polling, and chat protocol calls. They do not hard-code every model's private options. Always discover model keys, modes, app parameters, and model-specific controls from the API.

The published SDK package names, client classes, and BUBLE_API_KEY environment variable are retained as compatibility identifiers. They continue to call the Img2Vid API at https://img2vid.net.

Language Install
JavaScript / TypeScript npm install @buble/sdk
Python pip install buble-ai
Go go get github.com/bublehq/sdks/go
Rust cargo add buble
Swift .package(url: "https://github.com/bublehq/swift-sdk.git", from: "0.1.0")
Dart / Flutter dart pub add buble or flutter pub add buble
Elixir {:buble, "~> 0.1.0"}
Java ai.buble:buble-sdk:0.1.0
.NET dotnet add package Buble.SDK --version 0.1.2
PHP composer require buble/sdk
Ruby gem install buble

All SDK examples below read BUBLE_API_KEY from the environment when the API key is omitted. Keep this key on your server.

JavaScript / TypeScript

import { Buble } from '@buble/sdk';

const buble = new Buble();

const task = await buble.generations.create({
  model: 'google/nano-banana',
  mode: 'text_to_image',
  prompt: 'A cinematic product photo of a matte black espresso cup',
  aspect_ratio: '1:1',
  output_format: 'png',
});

const result = await buble.generations.wait(task.data.id);
console.log(result.data.result?.images?.[0]?.url);

Python

from buble_ai import Buble

client = Buble()

task = client.generations.create(
    model="google/nano-banana",
    mode="text_to_image",
    prompt="A cinematic product photo of a matte black espresso cup",
    aspect_ratio="1:1",
    output_format="png",
)

result = client.generations.wait(task["data"]["id"])
print(result["data"]["result"]["images"][0]["url"])

Go

client := buble.NewClient()

task, err := client.Generations.Create(ctx, &buble.CreateGenerationRequest{
	Model:  "google/nano-banana",
	Mode:   "text_to_image",
	Prompt: "A cinematic product photo of a matte black espresso cup",
	Params: map[string]any{
		"aspect_ratio":  "1:1",
		"output_format": "png",
	},
})
if err != nil {
	return err
}

result, err := client.Generations.Wait(ctx, task.Data.ID)
if err != nil {
	return err
}
fmt.Println(result.Data.Result.Images[0].URL)

Rust

use buble::{Client, CreateGenerationRequest, WaitOptions};

let client = Client::from_env()?;

let task = client.generations().create(
    CreateGenerationRequest::new("google/nano-banana")
        .mode("text_to_image")
        .prompt("A cinematic product photo of a matte black espresso cup")
        .param("aspect_ratio", "1:1")?
        .param("output_format", "png")?,
).await?;

let result = client
    .generations()
    .wait(&task.data.id, WaitOptions::default())
    .await?;

Swift

import Buble

let client = try BubleClient.fromEnvironment()

let task = try await client.generations.create(
    try CreateGenerationRequest(model: "google/nano-banana")
        .mode("text_to_image")
        .prompt("A cinematic product photo of a matte black espresso cup")
        .param("aspect_ratio", "1:1")
        .param("output_format", "png")
)

let result = try await client.generations.wait(task.data.id)
print(result.data.result?.images?.first?.url.absoluteString ?? "")

Dart / Flutter

import 'package:buble/buble.dart';

final client = BubleClient.fromEnvironment();

final task = await client.generations.create(
  CreateGenerationRequest(
    model: 'google/nano-banana',
    mode: 'text_to_image',
    prompt: 'A cinematic product photo of a matte black espresso cup',
  ).withParam('aspect_ratio', '1:1').withParam('output_format', 'png'),
);

final result = await client.generations.wait(task.data.id);
print(result.data.result?.images.firstOrNull?.url);

Elixir

client = Buble.Client.new!()

{:ok, task} =
  Buble.Generations.create(client, %{
    model: "google/nano-banana",
    mode: "text_to_image",
    prompt: "A cinematic product photo of a matte black espresso cup",
    aspect_ratio: "1:1",
    output_format: "png"
  })

{:ok, result} = Buble.Generations.wait(client, task["data"]["id"])
IO.puts(result["data"]["result"]["images"] |> List.first() |> Map.fetch!("url"))

Java

BubleClient client = BubleClient.fromEnv();

Envelope<GenerationTask> task = client.generations().create(
        CreateGenerationRequest.builder()
                .model("google/nano-banana")
                .mode("text_to_image")
                .prompt("A cinematic product photo of a matte black espresso cup")
                .param("aspect_ratio", "1:1")
                .param("output_format", "png")
                .build());

Envelope<GenerationTask> result = client.generations().wait(task.getData().getId());

.NET

using var client = BubleClient.FromEnv();

var task = await client.Generations.CreateAsync(new CreateGenerationRequest
{
    Model = "google/nano-banana",
    Mode = "text_to_image",
    Prompt = "A cinematic product photo of a matte black espresso cup"
}.WithParam("aspect_ratio", "1:1").WithParam("output_format", "png"));

var result = await client.Generations.WaitAsync(task!.Data!.Id!);

PHP

use Buble\BubleClient;
use Buble\Generations\CreateGenerationRequest;

$client = BubleClient::fromEnv();

$task = $client->generations()->create(
    CreateGenerationRequest::make(
        model: 'google/nano-banana',
        mode: 'text_to_image',
        prompt: 'A cinematic product photo of a matte black espresso cup',
    )->withParam('aspect_ratio', '1:1')
     ->withParam('output_format', 'png')
);

$result = $client->generations()->wait($task['data']['id']);

Ruby

require "buble"

client = Buble::Client.new

task = client.generations.create(
  model: "google/nano-banana",
  mode: "text_to_image",
  prompt: "A cinematic product photo of a matte black espresso cup",
  aspect_ratio: "1:1",
  output_format: "png"
)

result = client.generations.wait(task.dig("data", "id"))
puts result.dig("data", "result", "images", 0, "url")