Images & video
OpenAI-compatible image generation/editing endpoints, and submitting and polling asynchronous Grok Imagine video.
Images and video use endpoints shaped like the OpenAI / xAI originals, authenticated with Authorization: Bearer. Gemini's native image output is not here — it has no separate endpoint and still goes through generateContent, see Gemini API.
Image generation
/v1/images/generationsThe body matches the OpenAI Images API: model, prompt, and optionally n, size, quality, etc. Image models (such as gpt-image-2 and grok-imagine-image-2.0) are listed in Models.
curl https://soleapi.com/v1/images/generations \
-H "Authorization: Bearer $SOLEAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "A watercolor lighthouse at dawn",
"size": "1024x1024"
}'{
"created": 1757030400,
"data": [
{ "b64_json": "iVBORw0KGgo..." }
],
"usage": { "input_tokens": 12, "output_tokens": 0, "total_tokens": 12 }
}Image editing
/v1/images/editsmultipart/form-data: the image field carries the reference image(s), prompt the instruction; the remaining fields are the same as for generation.
curl https://soleapi.com/v1/images/edits \
-H "Authorization: Bearer $SOLEAPI_API_KEY" \
-F model=gpt-image-2 \
-F image=@lighthouse.png \
-F prompt="Turn the sky into a starry night"Images are billed per image, regardless of endpoint: see the model page for the unit price; n images cost n times as much. The generation endpoint accepts "stream": true for SSE partial previews and the final image, depending on the target model. Image endpoints allow inlined media, so the larger body limit of the chat endpoints applies.
Video generation (asynchronous)
Video is the gateway's only asynchronous endpoint: submitting returns just a job id, the upstream renders in the background, and the client polls until the result is ready.
/v1/videos/generationsThe body follows the xAI Grok Imagine fields: model (e.g. grok-imagine-video-1.5), prompt, and optionally duration (seconds), aspect_ratio, resolution, etc.
curl https://soleapi.com/v1/videos/generations \
-H "Authorization: Bearer $SOLEAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "grok-imagine-video-1.5",
"prompt": "A lighthouse in a storm, cinematic",
"duration": 6,
"aspect_ratio": "16:9"
}'
# => { "request_id": "8f0c…" }/v1/videos/editsVideo editing works the same way, with a reference video added to the body; the response is again a request_id.
/v1/videos/{request_id}Poll with the request_id returned on submit. Keep waiting while status is pending; on done, video.url is the rendered file and video.duration its length in seconds; failed / expired mean the upstream render failed or the result has expired.
curl https://soleapi.com/v1/videos/8f0c… \
-H "Authorization: Bearer $SOLEAPI_API_KEY"
# => { "status": "done", "video": { "url": "https://…/video.mp4", "duration": 6 } }Billing: nothing is charged on submit, only an estimate is held; the charge is settled when polling sees status = done, counting seconds by the duration you submitted (falling back to the rendered length only if you omitted it). Failed renders are free. Always poll to a terminal state — even if you no longer need the result, the gateway will query the upstream on your behalf and settle, so "not polling" does not mean "not paying". Poll every 5–10 seconds; polling counts toward RPM.
Related errors
| Message id | HTTP | Meaning |
|---|---|---|
video_job_missing | 400 | The polling path has no request_id. |
video_job_not_found | 404 | The job does not exist or belongs to another account. |
video_job_route_gone | 502 | The upstream used by the job has been removed; the result cannot be retrieved. |
video_job_unavailable | 500 | The job service is temporarily unavailable — retry later. |
Everything else matches the chat endpoints, see Errors.