
How to Split an Image into Editable Layers with the Seedream 5.0 Pro Layerize API
POST https://api.evolink.ai/v1/images/generations with model: "doubao-seedream-5.0-pro-layerize" and exactly one image URL. That returns a task ID, not an image — this model is asynchronous and takes about 120 seconds. Poll GET /v1/tasks/{task_id} until status is completed, then read the layers out of result_data.What You Actually Get Back
| Output | Format | What it is |
|---|---|---|
| Base image | Follows output_format (jpeg by default) | The background, rebuilt behind everything that was lifted off it |
| Layers 1…16 | Always PNG with alpha, regardless of output_format | One element each, transparent everywhere else |
The point worth pausing on is the base image. When Layerize lifts a headline off a poster, it does not leave a hole — it reconstructs what was behind the text. That is the difference between this and a segmentation mask, and it is why the output drops straight into a design tool instead of needing cleanup.
Three Ways to Target Layers
prompt field is optional, and each of the three ways to use it fits a different job.
1. Omit the prompt — automatic full decomposition
{
"model": "doubao-seedream-5.0-pro-layerize",
"image_urls": ["https://example.com/poster.png"],
"quality": "auto",
"output_format": "jpeg"
}With no prompt at all, the model finds every major element on its own — text blocks, subjects, decorations, background — and splits each into its own layer. This is the primary use of the model, and a complex poster routinely comes back as ten or more layers.
"prompt": "" reads upstream as "the user supplied an empty instruction" and loses the auto-detect behavior. Send no prompt key at all.2. Natural language — name the elements you want
{
"model": "doubao-seedream-5.0-pro-layerize",
"prompt": "Split out the parrot and the title text",
"image_urls": ["https://example.com/poster.png"],
"quality": "2K"
}Use this when you only care about two or three elements and don't want to pay for a full decomposition. Elements are identified semantically, so "the title text" works without you knowing where it sits.
3. Bbox coordinates — pin the exact region
{
"model": "doubao-seedream-5.0-pro-layerize",
"prompt": "title text<bbox>179 58 809 197</bbox>, 1 parrot<bbox>330 274 641 991</bbox>",
"image_urls": ["https://example.com/poster.png"],
"quality": "1.5K"
}<bbox> tag takes four numbers in normalized 0–1000 coordinates (not pixels), written as left top right bottom. Reach for this when natural language is ambiguous — two similar products in one frame, or repeated text blocks where "the heading" could mean either of two.bounding_box.normalized values off the layers it found, then re-run with those coordinates to get exactly the split you want.The Async Workflow
Step 1 — submit the task
curl -X POST https://api.evolink.ai/v1/images/generations \
-H "Authorization: Bearer $EVOLINK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seedream-5.0-pro-layerize",
"image_urls": ["https://example.com/poster.png"],
"quality": "auto"
}'The response is a task handle, not an image:
{
"id": "task-unified-1757165031-seedream5prolayerize",
"object": "image.generation.task",
"model": "doubao-seedream-5.0-pro-layerize",
"status": "pending",
"progress": 0,
"type": "image",
"task_info": { "can_cancel": true, "estimated_time": 120 },
"usage": { "billing_rule": "per_call", "credits_reserved": 39.168 }
}credits_reserved — that is an estimate reserved up front, sized for a worst-case split. Your actual charge is computed from the images that actually come back.Step 2 — poll until it finishes
curl https://api.evolink.ai/v1/tasks/task-unified-1757165031-seedream5prolayerize \
-H "Authorization: Bearer $EVOLINK_API_KEY"status moves through pending → processing → completed (or failed). Budget around 120 seconds; polling every 5 seconds is plenty. If you'd rather not poll, pass a callback_url on submit — HTTPS only, no internal IPs, and it fires after billing is confirmed, with up to 3 retries at 1s/2s/4s.Step 3 — read the layers
result_data carries metadata that lets you rebuild the composition on any canvas:| Field | Meaning |
|---|---|
z_index | Stacking order. 0 is the base image; layers start at 1 |
bounding_box.absolute | Position in base-image pixel coordinates |
bounding_box.normalized | Same box in 0–1000 coordinates |
name | Model-generated label, e.g. "scarlet macaw" |
description | Longer description of the element |
z_index: 0 — no name or bounding_box. Sorting by z_index and compositing each layer at its absolute box reproduces the original image exactly.Input Constraints Are Stricter Than Plain Generation
More requests fail here than anywhere else in the flow, because Layerize does not accept everything plain Seedream generation does.
| Constraint | Value |
|---|---|
| Image count | Exactly 1. Zero or two or more is an error |
| Formats | .png, .jpeg, .jpg only — webp is rejected |
| File size | ≤ 30MB |
| Total pixels | 262,144 to 36,000,000 in total — 512×512 is the smallest square that qualifies |
| Aspect ratio | Between 1:16 and 16:1 |
| URL | Must be directly fetchable by the server, or trigger a direct download |
quality is also narrower: layer mode accepts only the tiers auto, 1K, 1.5K, 2K. Passing a ratio like 16:9 or explicit pixels like 2048x2048 returns an error. With auto, output follows the input — kept as-is if the original lands between 921,600 and 4,624,220 pixels, bumped up to 1K below that, capped at 2K above.Billing: Count Output Images, Not Requests
On EvoLink, Layerize runs at 20% below BytePlus list price:
| Item | BytePlus list | EvoLink |
|---|---|---|
| Input image | $0.003 | $0.0024 |
| Output image, low tier (≤ 2,610,000 px) | $0.0225 | $0.018 |
| Output image, high tier (> 2,610,000 px) | $0.045 | $0.036 |
1K and 1.5K cost the same — both land in the low tier. The tier is decided per image, so a 2K base image is billed high while the small text layers lifted off it are billed low.Two worked examples:
Four Things That Will Trip You Up
- Sending
"prompt": ""instead of omitting the key. Kills auto-detection — the model's best feature. - Expecting
output_format: "png"to affect the layers. It only controls the base image. Layers are always PNG with alpha. - Treating a failed request as partial. There is no partial success. Any layer failing fails everything, and you are fully refunded — so retry logic should assume all-or-nothing.
- Letting the URLs expire. 24 hours, then they're gone. Download in the same job that polls.
FAQ
How many layers can I get?
Between 1 and 16 layers plus the base image, so at most 17 output images. You cannot request a specific number — the decomposition result decides.
Can I control which elements become layers?
<bbox> tags in normalized 0–1000 coordinates.Are the layers really transparent PNGs?
output_format. Only the base image follows that setting.How long does one call take?
callback_url if you don't want to poll.What happens if one layer fails?
The whole request fails — there is no partial success — and it is fully refunded.
Does it work on any image?
It needs a PNG or JPEG with at least 262,144 total pixels — 512×512, for example — under 30MB, with an aspect ratio between 1:16 and 16:1. webp is rejected even though plain generation accepts it.


