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
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 secondsconst 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-xxxxxxxxxxxxxxxxRequest Parameters
Core Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
model | string | Yes | seedream-v4.5-edit | Model identifier |
prompt | string | Yes | - | Description of how to edit the image, max 4000 chars |
image_urls | array | Yes | - | List of source image URLs (1-14 images required) |
aspect_ratio | string | - | 1:1 | Aspect ratio of the output image |
quality | string | - | 2K | Output 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 Count | Use Case |
|---|---|
| 1 image | Single image style transfer or editing |
| 2-3 images | Style blending from multiple references |
| 4+ images | Complex 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 styleSpecify Style Details
Add specific style characteristics you want to apply.
with soft edges, pastel colors, and visible brush strokesPreserve 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 sceneComplete 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
| Value | Ratio | Use Case |
|---|---|---|
1:1 | Square | Avatars, social media posts |
2:3 | Portrait | Portrait photography |
3:2 | Landscape | Landscape photography |
3:4 | Portrait | Magazine covers, posters |
4:3 | Landscape | Traditional photos |
16:9 | Widescreen | Video thumbnails, Banners |
9:16 | Vertical | Phone wallpapers, short video covers |
21:9 | Ultra-wide | Cinematic frames, website Hero images |
Resolution Options
| Value | Description |
|---|---|
2K | Standard resolution, faster generation |
4K | High resolution, suitable for printing and large displays |
Response Structure
Task Submission Response
After submitting an image edit request, the API returns a task ID:
| Field | Type | Description |
|---|---|---|
code | integer | Response status code, 0 indicates success |
message | string | Response message |
data.task_id | string | Unique identifier for the edit task |
{
"code": 0,
"message": "success",
"data": {
"task_id": "task_edit_abc123xyz"
}
}Status Query Interface
| Path Parameter | Type | Required | Description |
|---|---|---|---|
task_id | string | Yes | Image edit task ID |
Status Response Fields
| Field | Type | Description |
|---|---|---|
code | integer | Response status code, 0 indicates success |
message | string | Response message |
data.task_id | string | Task ID |
data.error_message | string | Error message |
data.status | string | Task status: pending / processing / completed / failed |
data.completed_at | integer | Completion timestamp (Unix timestamp) |
data.result | array | List of edited image URLs |
Task Status Description
| Status | Description | Recommended Action |
|---|---|---|
pending | Task submitted, waiting for processing | Continue polling, recommended interval 2 seconds |
processing | Task is being processed | Continue polling, recommended interval 2 seconds |
completed | Task completed, image edited | Get image URLs from result |
failed | Task failed | Check 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 Code | Description |
|---|---|
400 | Request parameter error (e.g., invalid image_urls, too many images) |
401 | Authentication failed, API Key invalid or missing |
403 | Insufficient balance or insufficient permissions |
404 | Task does not exist (when querying status) |
429 | Request too frequent, triggered rate limit |
500 | Internal 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.