A Practical Guide to Building Image Generation and Editing with Seedream

When you add image generation to a product, the hard part is usually not the prompt itself. It is choosing the right request shape, deciding when to run synchronously or asynchronously, and handling image edits without turning your backend into a pile of special cases.
This guide walks through the Seedream Images API as documented by Ace Data Cloud, using the real endpoint and fields from the integration reference. The goal is a practical builder-oriented starting point: generate a clean image from a prompt, edit an existing image, and move longer jobs into an async workflow.
What you can do
The Seedream Images API uses a single endpoint, POST https://api.acedata.cloud/seedream/images, for both generation and image editing. The basic request can include fields such as prompt, model, image, size, watermark, response_format, output_format, callback_url, and async.
From the documented examples, you can use it for:
- Text-to-image generation with
action: "generate", aprompt, and a Seedream model. - Image editing by passing one or more input image URLs in
image. - Layer decomposition with Seedream 5.0 Pro using
layer_decomposition: true. - Streaming output on supported Lite and 4.x models with
stream: true. - Long-running async jobs using
callback_urlorasync: true.
How it works
Every API call should send JSON and authenticate with a bearer token. The documented headers are:
accept: application/jsonfor normal JSON responses.authorization: Bearer ${token}for API authentication.content-type: application/jsonfor the request body.
For streaming output, the documentation notes that Lite and 4.x models should use accept: application/x-ndjson when stream: true. Streaming returns events such as image_generation.partial_succeeded or image_generation.partial_failed line by line, then one final image_generation.completed event with final usage.
Start with a small generation request
A minimal generation request uses action, model, and prompt. The default model documented for the API is doubao-seedream-5-0-lite-260128. The documentation is explicit that the model must be passed as the full model string; an abbreviation such as doubao-seedream-5.0-lite returns a 400.
curl -X POST 'https://api.acedata.cloud/seedream/images' \
-H 'accept: application/json' \
-H 'authorization: Bearer ${token}' \
-H 'content-type: application/json' \
-d '{
"action": "generate",
"model": "doubao-seedream-5-0-lite-260128",
"prompt": "A single matte blue cube centered on a clean white studio background, neutral lighting"
}'
A successful response includes success, task_id, trace_id, and a data list. Each result item includes fields such as prompt, size, and image_url. In a product, the simplest implementation is to store task_id and trace_id for debugging, then render or download the returned image_url.
Choose the right model and size
The documented model options include doubao-seedream-5-0-pro-260628, doubao-seedream-5-0-lite-260128, doubao-seedream-4-5-251128, and doubao-seedream-4-0-250828. The important implementation detail is that each model supports a different set of capabilities and size presets.
For size, the API supports two approaches that should not be mixed:
- Use a resolution preset and describe the aspect ratio naturally in the prompt.
- Pass explicit width and height values such as
2048x2048.
The documented preset support differs by model: Seedream 5.0 Pro supports 1K, 1.5K, and 2K; Seedream 5.0 Lite supports 2K, 3K, and 4K; Seedream 4.5 supports 2K and 4K; Seedream 4.0 supports 1K, 2K, and 4K.
Edit an existing image
For editing, pass the source image through image. The documentation shows that the field can contain one or more image URLs, and the request can include a prompt describing what should change. This is useful for product mockups, content localization, material changes, or turning a user-uploaded image into a controlled visual variant.
import requests
url = "https://api.acedata.cloud/seedream/images"
headers = {
"accept": "application/json",
"authorization": "Bearer {token}",
"content-type": "application/json"
}
payload = {
"model": "doubao-seedream-4-0-250828",
"prompt": "Keep the model pose and the liquid garment flowing shape unchanged. Change the clothing material from silver metal to completely transparent water (or glass). Through the liquid flow, the details of the model skin are visible. The light and shadow effect shifts from reflection to refraction.",
"image": ["https://ark-project.tos-cn-beijing.volces.com/doc_image/seedream4_5_imageToimage.png"],
"size": "2K",
"watermark": False
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)
For editing workflows, I usually recommend keeping the user-facing prompt short but storing the full backend prompt template. That makes it easier to reproduce a result when a user reports an issue, especially when combined with the returned trace_id.
Move longer jobs to async
The documentation notes that image generation may take around one to two minutes. Keeping a client request open for that long is often a poor fit for web apps, serverless functions, or chat-based tools. Seedream supports two async patterns:
- Set
callback_urlso the result is posted back to your service. - Set
async: trueand poll later with the/seedream/tasksinterface using the returnedtask_id.
If you already operate a public webhook endpoint, callback_url is clean. If you are building locally, inside an internal tool, or without a public URL, async: true is usually easier. In either case, persist task_id as your join key before returning control to the user.
Handle failures explicitly
The documented error shape includes success: false, an error object with code and message, and a trace_id. The reference lists errors such as 400 token_mismatched, 400 api_not_implemented, 401 invalid_token, 429 too_many_requests, and 500 api_error.
{
"success": false,
"error": {
"code": "api_error",
"message": "fetch failed"
},
"trace_id": "2cf86e86-22a4-46e1-ac2f-032c0f2a4e89"
}
For a production integration, do not collapse these into a generic “generation failed” message. Treat 401 invalid_token as an authentication issue, 429 too_many_requests as a retry/backoff case, and 500 api_error as a server-side failure worth logging with trace_id.
Putting it together
The cleanest first version is small: create one function that posts to /seedream/images, one database table for task_id, trace_id, request metadata, and result URLs, and one worker path for callbacks or polling. Once that foundation is stable, you can add model-specific choices such as Seedream 5.0 Pro layer decomposition, Lite streaming, or multi-image editing.
If you want to build against the original reference, read the full Seedream Images API integration guide.
Comments
Post a Comment