bytedance/seedream-4-5
Seedream 4.x and 5.0 Lite — BytePlus's workhorse image models.
Text-to-image and image-to-image, with `size` as a parameter and an optional batch mode that returns several related images from one request.
Faster than 5.0 Pro and available on both the synchronous and the polling route.
| Slug | bytedance/seedream-4-5 |
| Kind | image |
| Vendor | bytedance |
| Endpoint | POST /v1/byteplus/images/async |
Charged per job from what the generator reports it rendered — your Logs show the exact figure for each one; see balance and billing.
Calling it
curl https://api.sociaro.com/v1/byteplus/images/async \
-H "Authorization: Bearer $SOCIARO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "bytedance/seedream-4-5",
"prompt": "a paper boat on a rain-soaked street"
}'Parameters
Seedream 4.x / 5.0 Lite — text-to-image and image-to-image
| Field | Type | Required | Default | Values | What it does |
|---|---|---|---|---|---|
prompt | string | yes | — | text | What to generate. |
image | string[] | no | — | public https urls | Present -> image-to-image. |
size | string | no | 2048x2048 | presets per model, or WxH | 4.0 takes 1K/2K/4K; 4.5 takes 2K/4K; 5.0 Lite takes 2K/3K/4K. In pixels, both the area and the aspect ratio must be in range — the generator says which one you missed. |
output_format | string | no | jpeg | jpeg · png | |
response_format | string | no | url | url | The async route is url-only. |
watermark | boolean | no | false here | true · false | BytePlus defaults this ON; we default it off. |
seed | integer | no | random | — | Accepted and forwarded. NOT in the vendor's published field list, so treat reproducibility as unverified. |
sequential_image_generation | string | no | disabled | disabled · auto | `auto` returns a BATCH of related images instead of one. Billed per image actually generated. Seedream 5.0 Pro does not support this. |
sequential_image_generation_options | object | no | — | — | Settings for the batch above, per the vendor's reference. |
Anything not listed here is refused rather than ignored, so a typo fails loudly instead of quietly producing something else.
Worked example
curl https://api.sociaro.com/v1/byteplus/images/generations \
-H "Authorization: Bearer $SOCIARO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "bytedance/seedream-4-5",
"prompt": "a red paper boat on wet asphalt at night",
"size": "2K"
}'How a job runs
These routes are a pass-through: you send BytePlus's own body and get their own response back, with our additions beside it. Generation takes longer than a request should wait, so it goes in three moves — submit, poll, collect.
# 1. submit — the id comes back as `id`. There is NO `job_id` on THIS response
curl -sS https://api.sociaro.com/v1/byteplus/contents/generations/tasks \
-H "Authorization: Bearer $SOCIARO_API_KEY" -H "Content-Type: application/json" \
-d '{ "model": "…", "content": [ … ] }'
# -> { "id": "cgt-…" }
# 2. poll every 5-10 s
curl -sS https://api.sociaro.com/v1/byteplus/contents/generations/tasks/cgt-… \
-H "Authorization: Bearer $SOCIARO_API_KEY"
# -> { "status": "running", … }
# -> { "status": "succeeded", "content": { "video_url": "<the vendor's own link>" },
# "media_url": "https://api.sociaro.com/v1/media/<media_id>" }
# 3. collect — the opaque id IS the credential, no header needed
curl -sSL "https://api.sociaro.com/v1/media/<media_id>" -o out.mp4
Images use POST /v1/byteplus/images/async and its poll in the same shape, and the faster models
also answer synchronously at POST /v1/byteplus/images/generations — one request, the picture in
the response. A model whose render outlasts the gateway's ~2-minute ceiling is refused there by
name, telling you to use the async route.
Reading the poll
Two differences will bite a client written against the poll-style routes. The SUBMIT returns
id, not job_id — code reading job_id there gets nothing and cannot poll at all. And status
is the VENDOR'S vocabulary: running, succeeded, failed — not processing, completed,
failed. A check for completed on this route never becomes true, which reads as a job that never
finishes rather than as an error.
The POLL response does carry job_id beside the vendor's id, as a convenience, and it returns
the vendor's whole body — around twenty fields — rather than the five-field shape the other routes
use. Gate on status rather than on the poll's HTTP code.
Prefer media_url over the vendor's raw link. Both are returned: content.video_url (or
data[].url for images) is theirs, kept for compatibility and due to be removed once nobody reads
it; media_url is ours. Ours points at our host, hides the vendor's storage, and expires. A second
asset arrives on the same terms — return_last_frame gives content.last_frame_url with
last_frame_media_url beside it.
Collecting the result
media_url is a capability: the opaque id is the credential, so no Authorization header is
needed and anyone holding the link can fetch it. It expires within the hour — download rather
than store the link.
Rules the gateway adds
Your key must be granted this model — 403 otherwise — and either spelling satisfies the grant:
our catalogue id or the vendor's own native one.
Because this is a pass-through, unknown fields go to the generator rather than being refused here,
and it is the generator that decides. The exception is resolution, which we check ourselves: an
unsupported tier is silently ignored upstream, so you would ask for the higher one, be handed a
lower one, and be charged. A tier we cannot price is refused at submit, before any money is spent,
with a message naming the ones this model has.
Ranges and enums are the generator's own, so an out-of-range value comes back as its rejection, in its wording and with its numbers.