Learn how to generate images and videos with the June API.
Unlike chat completions, image and video generation is asynchronous: you submit a request, get back a request ID immediately, then poll for the result.
Overview
- Query
https://api.blockchain.info/ai/api/v1/images/modelsor.../videos/modelsto see the available models and the request types they support. - POST to
https://api.blockchain.info/ai/api/v1/images/queueor.../videos/queueand store the request ID that is returned. - Poll
https://api.blockchain.info/ai/api/v1/images/{id}or.../videos/{id}until the generation is complete.
Every endpoint requires your API key as a Bearer token (Authorization: Bearer $JUNE_API_KEY). See the Quickstart for how to create one.
Models & Request Support
The models endpoints return the list of models that June currently supports.
For each model, the response will contain the id, label, and requestTypes.
The requestTypes object maps each supported request type to its schema; this tells you how to build that kind of request and what options are available.
The example below shows the image model flux-2/dev/turbo supporting TEXT_TO_IMAGE and IMAGE_TO_IMAGE requests, i.e. image generation and image editing.
You can see that for TEXT_TO_IMAGE, this model requires a prompt string, and also supports optional image_size, seed, output_format and guidance_scale parameters; IMAGE_TO_IMAGE supports the same fields, but also requires an images array with between 1 and 4 images.
{
"models": [
{
"id": "flux-2/dev/turbo",
"label": "Flux.2 [dev] Turbo",
"requestTypes": {
"TEXT_TO_IMAGE": {
"type": "object",
"properties": {
"prompt": {
"type": "string",
"description": "Text description of the image to generate"
},
"image_size": {
"description": "The pixel dimensions of the generated output",
"default": "landscape_4_3",
"oneOf": [
{
"type": "string",
"enum": [ "square_hd", "square", "portrait_4_3", "portrait_16_9", "landscape_4_3", "landscape_16_9" ]
},
{
"type": "object",
"properties": {
"width": { "type": "integer", "minimum": 512, "maximum": 2048 },
"height": { "type": "integer", "minimum": 512, "maximum": 2048 }
},
"required": [ "width", "height" ],
"additionalProperties": false
}
]
},
"seed": {
"type": "integer",
"description": "Set a specific value to reproduce the same output across generations",
"minimum": -2147483648,
"maximum": 2147483647
},
"output_format": {
"type": "string",
"description": "The file format for the generated image",
"default": "png",
"enum": [ "jpeg", "png", "webp" ]
},
"guidance_scale": {
"type": "number",
"description": "Controls how closely the output follows your prompt; higher values produce more literal results",
"default": 2.5,
"minimum": 0,
"maximum": 20
}
},
"required": [ "prompt" ]
},
"IMAGE_TO_IMAGE": {
"type": "object",
"properties": {
"images": {
"type": "array",
"description": "Input images to edit or use as reference.",
"items": {
"type": "object",
"properties": {
"url": {
"type": "string"
}
},
"required": [ "url" ],
"additionalProperties": false
},
"maxItems": 4,
"supportedTypes": [ ".avif", ".gif", ".jpeg", ".jpg", ".png", ".webp" ],
"maxBytesTotal": 4000000
}
// prompt, image_size, seed, output_format and guidance_scale as in TEXT_TO_IMAGE
},
"required": [ "prompt", "images" ]
}
}
}
]
}
Any media you supply as input — the url fields inside images, videos, firstFrame and lastFrame — must be a base64-encoded data URL (for example data:image/png;base64,iVBORw0KGgo...). Plain http(s) links are not accepted as inputs. Check each field's supportedTypes and maxBytesTotal in the schema before uploading.
Generating an Image
The example below queues a TEXT_TO_IMAGE request, captures the returned request ID, then polls until the image is ready. While the generation is in progress, the poll endpoint returns a 204 No Content; once it completes, it returns a 200 with the result.
Match your polling interval to how long the generation is expected to take. Images are usually faster than videos, but times still vary a lot by model: a Flux [dev] image lands in a couple of seconds, while a model like GPT Image 2 can take ~60s, and a video a minute or two. The examples below poll every 2s as a safe default — drop to ~500ms for fast image models if you want the result sooner, or raise it to ~10s for videos to avoid hammering the endpoint while you wait.
# 1. Queue a generation request — store the returned id
curl https://api.blockchain.info/ai/api/v1/images/queue \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $JUNE_API_KEY" \
-d '{
"model": "flux-2/dev/turbo",
"type": "TEXT_TO_IMAGE",
"prompt": "A cool duck"
}'
# => { "id": "1770197b-a161-4406-8388-852ec215b5fb" }
# 2. Poll until the image is ready (204 = still generating, 200 = done)
curl https://api.blockchain.info/ai/api/v1/images/1770197b-a161-4406-8388-852ec215b5fb \
-H "Authorization: Bearer $JUNE_API_KEY"The queue request returns a request ID immediately:
{
"id": "1770197b-a161-4406-8388-852ec215b5fb"
}
Once the generation completes, the poll endpoint returns the generated image URLs. TEXT_TO_IMAGE produces a single image, but the response is always an array:
{
"images": [
{ "url": "data:image/png;base64,iVBORw0KGgo..." }
]
}
A 4xx or 5xx status from the poll endpoint means the generation failed.
Results are not kept forever: generated images are retained for 1 hour and videos for 3 hours after completion. Fetch the result within that window — after it expires, the media is deleted and polling the request ID will no longer return it.
Generating a Video
Video generation follows the same queue-and-poll flow, but uses the https://api.blockchain.info/ai/api/v1/videos/queue and .../videos/{id} endpoints, and a different set of request types. Inspect .../videos/models to see which ones a given model supports, then supply the media field(s) for that type.
For example, a FIRST_FRAME queue request looks like this — as with all input media, firstFrame.url is a base64 data URL:
{
"model": "<video-model-id>",
"type": "FIRST_FRAME",
"prompt": "Slowly pan across the scene as the sun rises",
"firstFrame": { "url": "data:image/png;base64,iVBORw0KGgo..." }
}
Polling works exactly as it does for images — 204 while in progress, then 200 when complete. The only difference is the response shape: a video request returns a single video object rather than an images array.
{
"video": { "url": "data:video/mp4;base64,AAAAIGZ0eXBpc29t..." }
}