Seedream v4.5 Image to Image

Seedream v4.5 Image to Image API documentation, edit and transform images based on source images and text prompts.

Seedream v4.5 Image Edit API allows you to transform and edit existing images based on text prompts and reference images.

  • Supports 1-14 source images as reference
  • Supports Chinese and English Prompts
  • Multiple aspect ratio options: 1:1, 2:3, 3:2, 3:4, 4:3, 16:9, 9:16, 21:9
  • High-resolution output: Supports 2K and 4K resolutions
  • Asynchronous task mode: Submit request and poll for results

Interface Definition

POST
https://api.apipod.ai/v1/images/generations

Asynchronous Task Mode

This API operates asynchronously. After submitting a request, you will receive a task ID, and you need to poll the status interface to get the result.

Steps: 1. Submit task with source images to get task_id → 2. Poll status interface until completion

# Step 1: Submit image edit task
curl --request POST \
  --url https://api.apipod.ai/v1/images/edits \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "seedream-v4.5-edit",
    "prompt": "Transform this portrait into an oil painting style, keeping the original composition but adding vibrant brush strokes and rich textures",
    "image_urls": [
      "https://example.com/images/source.jpg"
    ],
    "aspect_ratio": "3:4",
    "quality": "2K"
  }'

# Response example:
# {"code": 0, "message": "success", "data": {"task_id": "task_edit_abc123xyz"}}

# Step 2: Poll task status
curl --request GET \
  --url https://api.apipod.ai/v1/images/status/task_edit_abc123xyz \
  --header 'Authorization: Bearer <token>'
import requests
import time

API_KEY = "<token>"
BASE_URL = "https://api.apipod.ai/v1"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}

# Step 1: Submit image edit task
response = requests.post(
    f"{BASE_URL}/images/edits",
    headers=headers,
    json={
        "model": "seedream-v4.5-edit",
        "prompt": "Transform this portrait into an oil painting style, keeping the original composition but adding vibrant brush strokes",
        "image_urls": [
            "https://example.com/images/source.jpg"
        ],
        "aspect_ratio": "3:4",
        "quality": "2K"
    }
)

task_id = response.json()["data"]["task_id"]
print(f"Task submitted: {task_id}")

# Step 2: Poll task status
while True:
    status_response = requests.get(
        f"{BASE_URL}/images/status/{task_id}",
        headers=headers
    )
    data = status_response.json()["data"]

    if data["status"] == "completed":
        print("Image edit complete!")
        print("Image URL:", data["result"])
        break
    elif data["status"] == "failed":
        print("Task failed")
        break
    else:
        print(f"Status: {data['status']}, waiting...")
        time.sleep(2)  # Poll every 2 seconds
const API_KEY = "<token>";
const BASE_URL = "https://api.apipod.ai/v1";

const headers = {
  "Authorization": `Bearer ${API_KEY}`,
  "Content-Type": "application/json"
};

async function editImage() {
  // Step 1: Submit image edit task
  const submitResponse = await fetch(`${BASE_URL}/images/edits`, {
    method: "POST",
    headers,
    body: JSON.stringify({
      model: "seedream-v4.5-edit",
      prompt: "Transform this portrait into an oil painting style, keeping the original composition",
      image_urls: [
        "https://example.com/images/source.jpg"
      ],
      aspect_ratio: "3:4",
      quality: "2K"
    })
  });

  const { data: { task_id } } = await submitResponse.json();
  console.log(`Task submitted: ${task_id}`);

  // Step 2: Poll task status
  while (true) {
    const statusResponse = await fetch(
      `${BASE_URL}/images/status/${task_id}`,
      { headers }
    );
    const { data } = await statusResponse.json();

    if (data.status === "completed") {
      console.log("Image edit complete!");
      console.log("Image URL:", data.result);
      break;
    } else if (data.status === "failed") {
      console.log("Task failed");
      break;
    } else {
      console.log(`Status: ${data.status}, waiting...`);
      await new Promise(resolve => setTimeout(resolve, 2000));
    }
  }
}

editImage();
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

const (
    apiKey  = "<token>"
    baseURL = "https://api.apipod.ai/v1"
)

type SubmitResponse struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
    Data    struct {
        TaskID string `json:"task_id"`
    } `json:"data"`
}

type StatusResponse struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
    Data    struct {
        TaskID      string   `json:"task_id"`
        Status      string   `json:"status"`
        CompletedAt int64    `json:"completed_at"`
        Result      []string `json:"result"`
    } `json:"data"`
}

func main() {
    // Step 1: Submit image edit task
    payload := map[string]interface{}{
        "model":  "seedream-v4.5-edit",
        "prompt": "Transform this portrait into an oil painting style",
        "image_urls": []string{
            "https://example.com/images/source.jpg",
        },
        "aspect_ratio": "3:4",
        "quality":      "2K",
    }

    jsonData, _ := json.Marshal(payload)

    req, _ := http.NewRequest("POST", baseURL+"/images/edits", bytes.NewBuffer(jsonData))
    req.Header.Set("Authorization", "Bearer "+apiKey)
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, _ := ioutil.ReadAll(resp.Body)
    var submitResp SubmitResponse
    json.Unmarshal(body, &submitResp)

    taskID := submitResp.Data.TaskID
    fmt.Printf("Task submitted: %s\n", taskID)

    // Step 2: Poll task status
    for {
        req, _ := http.NewRequest("GET", baseURL+"/images/status/"+taskID, nil)
        req.Header.Set("Authorization", "Bearer "+apiKey)

        resp, _ := client.Do(req)
        body, _ := ioutil.ReadAll(resp.Body)
        resp.Body.Close()

        var statusResp StatusResponse
        json.Unmarshal(body, &statusResp)

        if statusResp.Data.Status == "completed" {
            fmt.Println("Image edit complete!")
            fmt.Println("Image URL:", statusResp.Data.Result)
            break
        } else if statusResp.Data.Status == "failed" {
            fmt.Println("Task failed")
            break
        } else {
            fmt.Printf("Status: %s, waiting...\n", statusResp.Data.Status)
            time.Sleep(2 * time.Second)
        }
    }
}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

public class SeedreamEditExample {
    private static final String API_KEY = "<token>";
    private static final String BASE_URL = "https://api.apipod.ai/v1";

    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();

        // Step 1: Submit image edit task
        String payload = """
        {
          "model": "seedream-v4.5-edit",
          "prompt": "Transform this portrait into an oil painting style",
          "image_urls": ["https://example.com/images/source.jpg"],
          "aspect_ratio": "3:4",
          "quality": "2K"
        }
        """;

        HttpRequest submitRequest = HttpRequest.newBuilder()
            .uri(URI.create(BASE_URL + "/images/edits"))
            .header("Authorization", "Bearer " + API_KEY)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(payload))
            .build();

        HttpResponse<String> submitResponse = client.send(submitRequest,
            HttpResponse.BodyHandlers.ofString());

        JsonObject submitJson = JsonParser.parseString(submitResponse.body()).getAsJsonObject();
        String taskId = submitJson.getAsJsonObject("data").get("task_id").getAsString();
        System.out.println("Task submitted: " + taskId);

        // Step 2: Poll task status
        while (true) {
            HttpRequest statusRequest = HttpRequest.newBuilder()
                .uri(URI.create(BASE_URL + "/images/status/" + taskId))
                .header("Authorization", "Bearer " + API_KEY)
                .GET()
                .build();

            HttpResponse<String> statusResponse = client.send(statusRequest,
                HttpResponse.BodyHandlers.ofString());

            JsonObject statusJson = JsonParser.parseString(statusResponse.body()).getAsJsonObject();
            String status = statusJson.getAsJsonObject("data").get("status").getAsString();

            if ("completed".equals(status)) {
                System.out.println("Image edit complete!");
                System.out.println("Image URL: " + statusJson.getAsJsonObject("data").get("result"));
                break;
            } else if ("failed".equals(status)) {
                System.out.println("Task failed");
                break;
            } else {
                System.out.println("Status: " + status + ", waiting...");
                Thread.sleep(2000);
            }
        }
    }
}

Authentication

All API calls require a Bearer Token in the Header.

Security Notice

Do not expose your API Key directly in browser frontend code. It is recommended to use it only on the server side.

Authorization: Bearer sk-xxxxxxxxxxxxxxxx

Request Parameters

Core Parameters

ParameterTypeRequiredDefaultDescription
modelstringYesseedream-v4.5-editModel identifier
promptstringYes-Description of how to edit the image, max 4000 chars
image_urlsarrayYes-List of source image URLs (1-14 images required)
aspect_ratiostring-1:1Aspect ratio of the output image
qualitystring-2KOutput image resolution

Source Images

Image Requirements

  • Minimum: 1 image required
  • Maximum: Up to 14 images supported
  • Format: JPEG, PNG, WebP
  • Accessibility: Images must be publicly accessible URLs

Use Cases for Multiple Images:

Image CountUse Case
1 imageSingle image style transfer or editing
2-3 imagesStyle blending from multiple references
4+ imagesComplex scene composition or multi-reference editing

Prompt Writing Tips for Image Editing

Describe the Transformation

Clearly describe how you want to transform the source image.

Transform this photo into a watercolor painting style

Specify Style Details

Add specific style characteristics you want to apply.

with soft edges, pastel colors, and visible brush strokes

Preserve or Modify Elements

Specify what to keep and what to change from the original.

keep the original composition but change the background to a sunset scene

Complete Prompt Example:

Transform this portrait into an oil painting style, keeping the original composition and facial features,
but adding vibrant brush strokes, rich textures, and warm golden lighting reminiscent of Renaissance portraits.

Aspect Ratio Options

ValueRatioUse Case
1:1SquareAvatars, social media posts
2:3PortraitPortrait photography
3:2LandscapeLandscape photography
3:4PortraitMagazine covers, posters
4:3LandscapeTraditional photos
16:9WidescreenVideo thumbnails, Banners
9:16VerticalPhone wallpapers, short video covers
21:9Ultra-wideCinematic frames, website Hero images

Resolution Options

ValueDescription
2KStandard resolution, faster generation
4KHigh resolution, suitable for printing and large displays

Response Structure

Task Submission Response

After submitting an image edit request, the API returns a task ID:

FieldTypeDescription
codeintegerResponse status code, 0 indicates success
messagestringResponse message
data.task_idstringUnique identifier for the edit task
{
  "code": 0,
  "message": "success",
  "data": {
    "task_id": "task_edit_abc123xyz"
  }
}

Status Query Interface

GET
https://api.apipod.ai/v1/images/status/{task_id}
Path ParameterTypeRequiredDescription
task_idstringYesImage edit task ID

Status Response Fields

FieldTypeDescription
codeintegerResponse status code, 0 indicates success
messagestringResponse message
data.task_idstringTask ID
data.error_messagestringError message
data.statusstringTask status: pending / processing / completed / failed
data.completed_atintegerCompletion timestamp (Unix timestamp)
data.resultarrayList of edited image URLs

Task Status Description

StatusDescriptionRecommended Action
pendingTask submitted, waiting for processingContinue polling, recommended interval 2 seconds
processingTask is being processedContinue polling, recommended interval 2 seconds
completedTask completed, image editedGet image URLs from result
failedTask failedCheck error message, resubmit task

Polling Recommendation

It is recommended to poll the task status every 2-3 seconds. Image editing usually takes 15-45 seconds depending on the number of source images. Do not poll too frequently to avoid triggering rate limits.

Error Handling

Status CodeDescription
400Request parameter error (e.g., invalid image_urls, too many images)
401Authentication failed, API Key invalid or missing
403Insufficient balance or insufficient permissions
404Task does not exist (when querying status)
429Request too frequent, triggered rate limit
500Internal server error
{
  "error": {
    "message": "image_urls must contain between 1 and 14 images",
    "type": "invalid_request_error",
    "code": "invalid_parameter"
  }
}

Best Practices

Ensure Image Accessibility

Make sure all source image URLs are publicly accessible and return valid image content.

Optimize Source Images

Use high-quality source images for better results. Recommended minimum resolution is 512x512.

Set Reasonable Polling Interval

It is recommended to poll every 2-3 seconds and set a maximum number of polls (e.g., 90 times) to avoid infinite waiting.

Cache Edited Images

Image URLs have a limited validity period. It is recommended to download and store them on your own server or CDN.

On this page

Seedream v4.5 Image to Image | APIPod Docs