The Seedream API format
Code written against the Seedream API works here by changing the base URL and the key: the same fields, the same response, the same error codes.
What you change
The base URL and the key. The path is the one that format uses, so both spellings of the base URL work: set it to https://api.tokenify.dev and your client builds /api/v3/images/generations itself, or set it to https://api.tokenify.dev/api/v3 and it appends the rest.
curl https://api.tokenify.dev/api/v3/images/generations \
-H "Authorization: Bearer $TOKENIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "bytedance/seedream-5.0-pro",
"prompt": "A still life of three pears, soft window light",
"size": "2K"
}'model takes our ids, and it also takes the model ids that format uses — so a request that names a model the way your existing code does keeps working. The reply echoes whichever you sent, which is what a client comparing the two expects.
/v1/images/generations, on /v1/chat/completions and in /v1/models the only names are ours.The fields
| Field | Here |
|---|---|
prompt | Required, unless you send an image to work from. |
image | One string or an array. An https URL or a data URI. The per-model ceiling is in /v1/models as max_input_images. |
size | A tier or WIDTHxHEIGHT, per model. The tiers and the range are on the image generation page. |
response_format | url (the default here, as in that format) or b64_json. Our links last 7 days. |
output_format | png or jpeg. |
background | transparent or opaque, on the models that have it. Transparent needs png. |
watermark | false by default here, which is the one default we changed. Send true to have the mark. |
sequential_image_generation | With sequential_image_generation_options.max_images, asks for several images. The ceiling is per model. disabled together with a max_images above one is a 400: the two halves of that request disagree about how many images you are paying for, so neither reading of it is ours to pick. |
layer_decomposition | Splits one image into a base and its layers. See layer decomposition. |
Accepted and ignored: optimize_prompt_options, seed, guidance_scale. Refused with a 400 naming the field: stream (not yet), and anything unrecognised.
The reply
{
"model": "bytedance/seedream-5.0-pro",
"created": 1760000000,
"data": [{ "url": "https://img.tokenify.dev/…", "size": "2048x2048", "output_format": "jpeg" }],
// Ours, not part of that format: Unix seconds, 7 days out.
"expires_at": 1760604800,
"usage": {
"generated_images": 1,
"input_images": 0,
// Their metering rule — the sum of width x height over the images in this
// reply, divided by 256. Not what you are charged on: the charge is per image.
"output_tokens": 16384,
"total_tokens": 16384
}
}Where we differ
| There | Here | |
|---|---|---|
| Link lifetime | 24 hours | 7 days, and the reply says when in expires_at |
| Watermark | On by default | Off by default; send watermark: true for it |
| Streaming | Supported on some models | A 400. The reply is one JSON document |
| Unknown fields | Ignored | A 400 naming the field, so a parameter you expected to work cannot silently do nothing |
| Models | Several generations of them | The three on our models page. A model id we do not serve is a 404 listing what we do. |
Errors
The envelope and the codes are that format’s, so a client switching on error.code keeps working:
{ "error": { "code": "InvalidParameter", "message": "…" } }| Code | When |
|---|---|
InvalidParameter | A field is wrong: the size, an image, an unknown parameter. |
MissingParameter | No prompt and no image, or no model. |
InvalidEndpointOrModel.NotFound | A model we do not serve. |
AccessDenied | This key is not permitted to use that model. |
AccountOverdueError | Your balance will not cover the request. |
SensitiveContentDetected | The content policy refused the request. |
ModelAccountIpmRateLimitExceeded | Above your images a minute. Retry-After says when. |
InternalServiceError | Our side or the model’s. Nothing is charged. |
Last updated 2026-10-12.