Images and video at the provider’s price
Call Seedream 5.0, Nano Banana 2.1 and Gemini Omni Flash 1.1 through your Ghostmotion workspace with a Ghostmotion API key. Each takes its provider’s own request body and costs exactly its provider’s list price, at one credit per US dollar. The same keys, workspace credits and spending limits apply as for the video API. They are available where your workspace has them; Integrations shows the ones it does.
Seedream 5.0
BytePlus’s image model, in Pro (dola-seedream-5-0-pro-260628), Lite (seedream-5-0-lite-260128) and Flash (dola-seedream-5-0-flash-260915). The body is BytePlus ModelArk’s images/generations request: prompt, up to 10 reference image URLs to edit or combine, and size: 1K, 1.5K or 2K for Pro and Flash, 2K or 4K for Lite, or WIDTHxHEIGHT. Lite also makes a set of related images with sequential_image_generation: "auto" and max_images. Priced per image made at BytePlus’s prices: Pro $0.045 up to 1.5K (2.61 million pixels) and $0.09 above, plus $0.003 for each reference image after the first; Lite $0.035; Flash $0.018. When BytePlus can’t make a task, the same task is made by another provider at BytePlus’s price.
curl --fail-with-body "https://app.ghostmotion.ai/api/v1/seedream/images/generations" \
-H "Authorization: Bearer $GHOSTMOTION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "dola-seedream-5-0-pro-260628",
"prompt": "A paper-cut lighthouse on a stormy coast, warm window light",
"size": "2K",
"request_id": "lighthouse-001"
}'export TASK_ID='ID_FROM_RESPONSE'
curl --fail-with-body "https://app.ghostmotion.ai/api/v1/seedream/images/generations/$TASK_ID" \
-H "Authorization: Bearer $GHOSTMOTION_API_KEY"At succeeded, data[].url are the images, as BytePlus returns them, and usage.generated_images is what was charged.
Nano Banana 2.1
Google’s image model (gemini-nano-banana-2.1), with the Gemini API’s own contents and generationConfig. Put the prompt in a text part and up to 14 images in file_data parts with a public https file_uri. Set imageConfig.imageSize (1K or 2K) and aspectRatio. Charged exactly what Google bills: the tokens Google counts for it (input, text and thinking, and the image) at its list prices, about $0.04 for a 1K image; usage.tokens shows them. 4K is not offered until Google publishes one price for it.
curl --fail-with-body "https://app.ghostmotion.ai/api/v1/gemini/models/gemini-nano-banana-2.1/tasks" \
-H "Authorization: Bearer $GHOSTMOTION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Turn this sketch into a glossy product photo on white"
},
{
"file_data": {
"file_uri": "https://example.com/sketch.png",
"mime_type": "image/png"
}
}
]
}
],
"generationConfig": {
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "2K"
}
},
"request_id": "sketch-001"
}'Gemini Omni Flash 1.1
Google’s video model (gemini-omni-1.1-flash), on the same endpoints. Give a text part and up to 3 images and 3 reference videos as file_data parts. Set videoConfig.aspectRatio (16:9 or 9:16) and the length to ask for, durationSeconds (3–10; Google sets the final length), or task: "edit" or "extend" with one video. Made at 720p, the resolution Google publishes a price for, and charged the tokens Google counts for it, about $0.10 a second of video.
curl --fail-with-body "https://app.ghostmotion.ai/api/v1/gemini/models/gemini-omni-1.1-flash/tasks" \
-H "Authorization: Bearer $GHOSTMOTION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "A paper boat drifting down a rainy street, close tracking shot"
}
]
}
],
"generationConfig": {
"videoConfig": {
"aspectRatio": "16:9",
"resolution": "720p",
"durationSeconds": 6
}
},
"request_id": "boat-001"
}'export TASK_ID='ID_FROM_RESPONSE'
curl --fail-with-body "https://app.ghostmotion.ai/api/v1/gemini/tasks/$TASK_ID" \
-H "Authorization: Bearer $GHOSTMOTION_API_KEY"At succeeded, the image or video is a file_data part of candidates[0].content. When Google can’t make a task, the same task is made by another provider at Google’s price.
Links, failures and MCP
Output links are valid for one hour; read the task again for fresh ones. They follow a redirect to temporary storage and need no bearer header. A failed task’s error says why; it was not charged. Media must be public https URLs: data: URLs and inline_data are refused. Where your workspace has a model, MCP clients get its tools too: create_seedream_task and get_seedream_task, or create_gemini_task and get_gemini_task.
Reference
Create Seedream images
POST /api/v1/seedream/images/generations
Generate or edit images with Seedream 5.0 (Pro, Lite or Flash) in BytePlus ModelArk's own images/generations request shape. Returns a task id at once; poll get_seedream_task until it succeeds or fails. Costs exactly BytePlus's list price per image, one credit per US dollar.
Required permission: videos:write
Unlike BytePlus's synchronous call, this returns a task to poll. BytePlus's prices: Pro $0.045 an image up to 2.61 million pixels (1.5K) and $0.09 above, plus $0.003 for each reference image after the first; Lite $0.035; Flash $0.018. Reference images are public https URLs (image, up to 10). Lite alone makes sets: with sequential_image_generation auto, up to max_images related images, each charged. When BytePlus can't make a task, the same task is made on another provider at BytePlus's price. Nothing made, nothing charged. Reuse request_id and the same body to retry.
Request body
request_idstring · optionalOptional retry identity: the same id and body returns the same task. Not part of BytePlus's API.
at least 1 character; up to 128 characters
modelstring · requiredThe Seedream 5.0 tier.
dola-seedream-5-0-pro-260628 · seedream-5-0-lite-260128 · dola-seedream-5-0-flash-260915
promptstring · requiredWhat to make, or how to change the reference images.
at least 1 character; up to 5,000 characters
imagearray · optionalReference images to edit or combine, as public https URLs. A single string is accepted too.
up to 10 items
sizestring · optionalPro and Flash: 1K, 1.5K or 2K; Lite: 2K or 4K; or WIDTHxHEIGHT up to the tier's largest size (each side at least 256). Defaults to 2K. Pro is priced by size: above 2.61 million pixels costs $0.09.
seedinteger · optionalSeed for repeatable results; -1 for random.
minimum -1; maximum 2147483647
sequential_image_generationstring · optionalLite only: auto makes a set of related images; disabled (the default) makes one.
disabled · auto
sequential_image_generation_optionsobject · optionalsequential_image_generation_options.max_imagesinteger · optionalThe most images an auto set may make. Each is charged.
minimum 1; maximum 15
watermarkboolean · optionalAdd a watermark. Defaults to false.
response_formatstring · optionalAlways url: images are returned as links.
url
Example request
curl --fail-with-body "https://app.ghostmotion.ai/api/v1/seedream/images/generations" \
-H "Authorization: Bearer $GHOSTMOTION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "dola-seedream-5-0-pro-260628",
"prompt": "A paper-cut lighthouse on a stormy coast, warm window light",
"size": "2K",
"request_id": "lighthouse-001"
}'Response · 200
{
"id": "0190e2c4-1b2c-4d3e-8f40-223456789abc",
"model": "dola-seedream-5-0-pro-260628",
"status": "queued",
"created": 1793361600,
"size": "2K",
"credits": {
"price": null,
"charged": null,
"reserved": 0.09
},
"poll_after_seconds": 5
}All response fields
idstring · requiredThe id returned when the task was created.
at least 1 character
modelstring · requiredThe Seedream tier.
statusstring · requiredqueued, running, then succeeded or failed.
queued · running · succeeded · failed
creatednumber · requiredUnix seconds.
sizestring · optionalThe size asked for.
dataarray · optionalThe images, when it succeeded.
data[].urlstring · requiredAbsolute URL.
data[].sizestring · optionalWIDTHxHEIGHT, when known.
url_expires_atstring · optionalISO 8601 UTC timestamp.
usageobject · optionalusage.generated_imagesnumber · requiredImages made: what the price counts.
errorobject · optionalerror.codestring · requiredStable failure code.
error.messagestring · requiredWhy it failed; a failed task is not charged.
creditsobject · requiredcredits.pricenumber | null · requiredThe provider's list price for what was made, in credits (one per USD); null until it succeeds.
credits.chargednumber | null · requiredCredits charged; null until the task ends.
credits.reservednumber · requiredCredits held while the task runs.
poll_after_secondsnumber · optionalPresent while queued or running: wait this long before checking again.
Errors
unauthorized, permission_denied, not_found, invalid_request, insufficient_credits, allowance_exhausted, cap_too_low, idempotency_conflict, rate_limited, internal_error, temporarily_unavailable.
Check Seedream images
GET /api/v1/seedream/images/generations/{task_id}
Get a Seedream task: its status, and when it succeeded BytePlus's response shape (data[].url, usage.generated_images) and its price in credits.
Required permission: projects:read
Each data[].url is a Ghostmotion link that expires after one hour: read the task again for fresh ones. A failed task's error says why; it was not charged.
Path parameters
task_idstring · requiredThe id returned when the task was created.
at least 1 character
Query parameters
No query parameters required.
Example request
curl --fail-with-body "https://app.ghostmotion.ai/api/v1/seedream/images/generations/$TASK_ID" \
-H "Authorization: Bearer $GHOSTMOTION_API_KEY"Response · 200
{
"id": "0190e2c4-1b2c-4d3e-8f40-223456789abc",
"model": "dola-seedream-5-0-pro-260628",
"status": "succeeded",
"created": 1793361600,
"size": "2K",
"credits": {
"price": 0.045,
"charged": 0.045,
"reserved": 0
},
"data": [
{
"url": "https://app.ghostmotion.ai/api/v1/media/example-token",
"size": "2048x2048"
}
],
"url_expires_at": "2026-11-01T13:02:00.000Z",
"usage": {
"generated_images": 1
}
}All response fields
idstring · requiredThe id returned when the task was created.
at least 1 character
modelstring · requiredThe Seedream tier.
statusstring · requiredqueued, running, then succeeded or failed.
queued · running · succeeded · failed
creatednumber · requiredUnix seconds.
sizestring · optionalThe size asked for.
dataarray · optionalThe images, when it succeeded.
data[].urlstring · requiredAbsolute URL.
data[].sizestring · optionalWIDTHxHEIGHT, when known.
url_expires_atstring · optionalISO 8601 UTC timestamp.
usageobject · optionalusage.generated_imagesnumber · requiredImages made: what the price counts.
errorobject · optionalerror.codestring · requiredStable failure code.
error.messagestring · requiredWhy it failed; a failed task is not charged.
creditsobject · requiredcredits.pricenumber | null · requiredThe provider's list price for what was made, in credits (one per USD); null until it succeeds.
credits.chargednumber | null · requiredCredits charged; null until the task ends.
credits.reservednumber · requiredCredits held while the task runs.
poll_after_secondsnumber · optionalPresent while queued or running: wait this long before checking again.
Errors
unauthorized, permission_denied, not_found, rate_limited, internal_error, temporarily_unavailable.
Create a Nano Banana image or Omni Flash video
POST /api/v1/gemini/models/{model}/tasks
Generate an image with Nano Banana 2.1 (gemini-nano-banana-2.1) or a video with Gemini Omni Flash 1.1 (gemini-omni-1.1-flash), with the Gemini API's own contents and generationConfig. Returns a task id at once; poll get_gemini_task until it succeeds or fails. Costs exactly Google's list price, one credit per US dollar.
Required permission: videos:write
Media are file_data parts with a public https file_uri; inline_data is refused. Nano Banana takes generationConfig.imageConfig (aspectRatio, imageSize 1K or 2K); Omni Flash takes generationConfig.videoConfig (aspectRatio 16:9 or 9:16, resolution 720p, durationSeconds 3 to 10, task generate, edit or extend). Each is charged exactly what Google bills: the tokens Google counts for it (input, text and thinking, and the image or video) at Google's list prices, shown in usage.tokens. A 1K image is about $0.04; 720p video about $0.10 a second. Sizes and resolutions Google publishes no single price for are not offered yet. When Google can't make a task, the same task is made on another provider at Google's price. Nothing made, nothing charged.
Path parameters
modelstring · requiredThe model, in the path.
gemini-nano-banana-2.1 · gemini-omni-1.1-flash
Request body
request_idstring · optionalOptional retry identity: the same id and body returns the same task. Not part of the Gemini API.
at least 1 character; up to 128 characters
contentsarray · requiredOne user turn: its parts are one text part and any file_data parts (Nano Banana: up to 14 images; Omni Flash: up to 3 images and 3 videos). inline_data is refused.
up to 1 items
contents[].rolestring · optionalAlways user.
user
contents[].partsarray · requiredA text part and file_data parts.
up to 18 items
contents[].parts[].textstring · optionalThe prompt: exactly one part carries it.
up to 5,000 characters
contents[].parts[].file_dataobject · optionalcontents[].parts[].file_data.file_uristring · requiredPublic https URL of an image or video. Fetched from a public address only.
up to 2,048 characters
contents[].parts[].file_data.mime_typestring · requiredThe file's type.
image/png · image/jpeg · image/webp · video/mp4 · video/quicktime
generationConfigobject · optionalgenerationConfig.responseModalitiesarray · optionalIMAGE for Nano Banana, VIDEO for Omni Flash; TEXT may be added.
up to 2 items
generationConfig.imageConfigobject · optionalgenerationConfig.imageConfig.aspectRatiostring · optionalNano Banana's frame shape. Left out, the model chooses.
21:9 · 16:9 · 3:2 · 4:3 · 5:4 · 1:1 · 4:5 · 3:4 · 2:3 · 9:16
generationConfig.imageConfig.imageSizestring · optionalNano Banana's size. Defaults to 1K. 4K is not offered until Google publishes one price for it.
1K · 2K
generationConfig.videoConfigobject · optionalgenerationConfig.videoConfig.aspectRatiostring · optionalOmni Flash's frame shape. Defaults to 16:9.
16:9 · 9:16
generationConfig.videoConfig.resolutionstring · optionalOmni Flash's resolution: 720p, the one Google publishes a price for.
720p
generationConfig.videoConfig.durationSecondsinteger · optionalThe length to ask for (default 8). Google sets the final length, 3 to 10 seconds; you pay for what is delivered. Not for an edit or extension.
minimum 3; maximum 10
generationConfig.videoConfig.taskstring · optionalgenerate (the default), edit the one given video, or extend it.
generate · edit · extend
generationConfig.seedinteger · optionalSeed for repeatable results.
minimum 0; maximum 2147483647
Example request
curl --fail-with-body "https://app.ghostmotion.ai/api/v1/gemini/models/gemini-nano-banana-2.1/tasks" \
-H "Authorization: Bearer $GHOSTMOTION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Turn this sketch into a glossy product photo on white"
},
{
"file_data": {
"file_uri": "https://example.com/sketch.png",
"mime_type": "image/png"
}
}
]
}
],
"generationConfig": {
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "2K"
}
},
"request_id": "sketch-001"
}'Response · 200
{
"id": "0190e2c4-1b2c-4d3e-8f40-323456789abc",
"model": "gemini-nano-banana-2.1",
"status": "queued",
"createTime": "2026-11-01T12:00:00.000Z",
"credits": {
"price": null,
"charged": null,
"reserved": 0.0504
},
"poll_after_seconds": 5
}All response fields
idstring · requiredThe id returned when the task was created.
at least 1 character
modelstring · requiredThe model.
statusstring · requiredqueued, running, then succeeded or failed.
queued · running · succeeded · failed
createTimestring · requiredISO 8601 UTC timestamp.
candidatesarray · optionalThe output, when it succeeded, as the Gemini API's candidate with file_data parts.
candidates[].contentobject · requiredcandidates[].content.rolestring · requiredmodel
candidates[].content.partsarray · requiredOne file_data part per output.
candidates[].content.parts[].file_dataobject · requiredcandidates[].content.parts[].file_data.file_uristring · requiredAbsolute URL.
candidates[].content.parts[].file_data.mime_typestring · requiredThe output's type.
candidates[].finishReasonstring · requiredSTOP
uri_expires_atstring · optionalISO 8601 UTC timestamp.
usageobject · optionalusage.imagesnumber · optionalImages made (Nano Banana).
usage.secondsnumber · optionalSeconds of video made (Omni Flash).
errorobject · optionalerror.codestring · requiredStable failure code.
error.messagestring · requiredWhy it failed; a failed task is not charged.
creditsobject · requiredcredits.pricenumber | null · requiredThe provider's list price for what was made, in credits (one per USD); null until it succeeds.
credits.chargednumber | null · requiredCredits charged; null until the task ends.
credits.reservednumber · requiredCredits held while the task runs.
poll_after_secondsnumber · optionalPresent while queued or running: wait this long before checking again.
Errors
unauthorized, permission_denied, not_found, invalid_request, insufficient_credits, allowance_exhausted, cap_too_low, idempotency_conflict, rate_limited, internal_error, temporarily_unavailable.
Check a Nano Banana or Omni Flash task
GET /api/v1/gemini/tasks/{task_id}
Get a Nano Banana or Omni Flash task: its status, and when it succeeded the image or video as file_data parts in the Gemini API's candidate shape, with usage and its price in credits.
Required permission: projects:read
Each file_uri is a Ghostmotion link that expires after one hour: read the task again for fresh ones. A failed task's error says why; it was not charged.
Path parameters
task_idstring · requiredThe id returned when the task was created.
at least 1 character
Query parameters
No query parameters required.
Example request
curl --fail-with-body "https://app.ghostmotion.ai/api/v1/gemini/tasks/$TASK_ID" \
-H "Authorization: Bearer $GHOSTMOTION_API_KEY"Response · 200
{
"id": "0190e2c4-1b2c-4d3e-8f40-323456789abc",
"model": "gemini-nano-banana-2.1",
"status": "succeeded",
"createTime": "2026-11-01T12:00:00.000Z",
"credits": {
"price": 0.0504,
"charged": 0.0504,
"reserved": 0
},
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"file_data": {
"file_uri": "https://app.ghostmotion.ai/api/v1/media/example-token",
"mime_type": "image/png"
}
}
]
},
"finishReason": "STOP"
}
],
"uri_expires_at": "2026-11-01T13:02:00.000Z",
"usage": {
"images": 1
}
}All response fields
idstring · requiredThe id returned when the task was created.
at least 1 character
modelstring · requiredThe model.
statusstring · requiredqueued, running, then succeeded or failed.
queued · running · succeeded · failed
createTimestring · requiredISO 8601 UTC timestamp.
candidatesarray · optionalThe output, when it succeeded, as the Gemini API's candidate with file_data parts.
candidates[].contentobject · requiredcandidates[].content.rolestring · requiredmodel
candidates[].content.partsarray · requiredOne file_data part per output.
candidates[].content.parts[].file_dataobject · requiredcandidates[].content.parts[].file_data.file_uristring · requiredAbsolute URL.
candidates[].content.parts[].file_data.mime_typestring · requiredThe output's type.
candidates[].finishReasonstring · requiredSTOP
uri_expires_atstring · optionalISO 8601 UTC timestamp.
usageobject · optionalusage.imagesnumber · optionalImages made (Nano Banana).
usage.secondsnumber · optionalSeconds of video made (Omni Flash).
errorobject · optionalerror.codestring · requiredStable failure code.
error.messagestring · requiredWhy it failed; a failed task is not charged.
creditsobject · requiredcredits.pricenumber | null · requiredThe provider's list price for what was made, in credits (one per USD); null until it succeeds.
credits.chargednumber | null · requiredCredits charged; null until the task ends.
credits.reservednumber · requiredCredits held while the task runs.
poll_after_secondsnumber · optionalPresent while queued or running: wait this long before checking again.
Errors
unauthorized, permission_denied, not_found, rate_limited, internal_error, temporarily_unavailable.