A Practical Guide to Building Image Generation and Editing with Seedream

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", a prompt, 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_url or async: true.

How it works

Every API call should send JSON and authenticate with a bearer token. The documented headers are:

  • accept: application/json for normal JSON responses.
  • authorization: Bearer ${token} for API authentication.
  • content-type: application/json for 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_url so the result is posted back to your service.
  • Set async: true and poll later with the /seedream/tasks interface using the returned task_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

Popular posts from this blog

Artistic QR Code API Integration Guidance

How to Configure Claude Code with CC Switch and Ace Data Cloud

How to Build a Server-Side Image Editing Workflow with GPT-Image-2