Reference
Workflow API
Introduction
The Workflow API lets you trigger a published imageat workflow with a single HTTP request, poll for completion, and receive CDN-hosted outputs. Every run is metered and billed against the API key's owning account.
A typical integration is three calls: POST to create a run, GET (or subscribe via SSE) to track progress, and then read CDN URLs from the final response.
Authentication
All requests are authenticated with an API key sent as a Bearer token. Create keys from your Projects page. Keys start with iat_live_ (production) or iat_test_ (sandbox).
Authorization: Bearer iat_live_xxxxxxxxxxxxxxxx
Keep your API key on the server. Never expose it in client-side code or commit it to source control. Revoke and rotate from the Projects page if a key is exposed.
Model pricing overview
API and MCP requests spend your website credits (subscription and purchased) at the same rates as the website. Once those run out, usage bills your prepaid USD API balance at the prices below, which match the API pricing page and show the minimum supported configuration.
| Model | Starts at | Minimum configuration |
|---|---|---|
| nano-banana-2-lite | From $0.08 / image | 1 image · 512px |
| nano-banana-2.1 | From $0.16 / image | 1 image · 1K |
| nano-banana-2 | From $0.16 / image | 1 image · 1K |
| nano-banana-pro | From $0.40 / image | 1 image · 1K |
| midjourney-v8 | From $0.18 / 4 images | 4 images per run · 1K |
| gpt-image-2.5 | From $0.02 / image | 1 image · low quality · 1K |
| gpt-image-2 | From $0.02 / image | 1 image · low quality · 1K |
| seedream-5.0-pro | From $0.14 / image | 1 image · 1K |
| seedream-5.0-lite | From $0.07 / image | 1 image · 1K |
| ideogram/remove-background | $0.01 / image | 1 JPEG, PNG, or WebP · transparent PNG |
| minimax-h3-max | From $0.25 / video | 5 seconds · 480p |
| seedance25 | From $0.83 / video | 4 seconds · 480p |
| midjourney-v8 | From $0.18 / 4 videos | 4 × 5 seconds per run · 480p |
| pixverse | From $0.09 / second | 720p · audio off |
| Qwen 3.8 family | $0.00117/second | Billed by model execution time |
| Other LLM models | Usage-based | Final USD charge is returned in billing.amount_usd |
numImages. Video cost changes with duration, resolution, audio, and mode. Qwen 3.8 is billed by model execution time. Requests reserve balance up front, refund the unused amount, and return the final charge in billing.amount_usd.Image generation models
Generate new images or edit references through one JSON endpoint. Switch models without rebuilding your integration.
nano-banana-proNano Banana Pro
High-fidelity generation and editing with up to 4K output.
From $0.40 / image
nano-banana-2.1Nano Banana 2.1
Google's newest Nano Banana: up to 4K, extreme 8:1 to 1:8 ratios, up to 14 references, and optional web search grounding.
From $0.16 / image
nano-banana-2Nano Banana 2
Fast, cost-efficient generation for iterative creative work.
From $0.16 / image
gpt-image-2.5GPT Image 2.5
OpenAI's newest image model: five quality tiers, scoped edits, and transparent cut-outs. Add gpt-image-2.5-sunburst for the slower, finer-detail variant.
From $0.02 / image
midjourney-v8Midjourney V8
Midjourney V8.2 with stylize, chaos, weird, and style references. Every run returns 4 images; native 2K HD optional.
From $0.18 / 4 images
gpt-image-2GPT Image 2
Precise instruction following with selectable quality tiers.
From $0.02 / image
seedream-5.0-proSeedream 5 Pro
High-fidelity ByteDance generation and reference-guided editing.
From $0.14 / image
seedream-5.0-proSeedream V5 Pro Unrestricted
The catalog experience for Seedream V5 Pro; use the supported Pro model ID through the API.
From $0.14 / image
ideogram/remove-backgroundIdeogram Remove Background
Remove backgrounds while preserving hair, glass, text, and fine edges in a transparent PNG.
$0.01 / image
POST /v1/imagesGenerate or edit an image
Send a prompt for text-to-image. Add one or more public image URLs in images to edit or guide the result.
curl -X POST "https://api.imageat.com/v1/images" \
-H "Authorization: Bearer $IMAGEAT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "nano-banana-pro",
"prompt": "A cinematic product photograph on sculpted stone",
"aspectRatio": "1:1",
"resolution": "2K",
"outputFormat": "png",
"numImages": 1
}'{
"url": "https://cdn.imageat.com/generated/image.png",
"urls": ["https://cdn.imageat.com/generated/image.png"],
"prompt": "A cinematic product photograph on sculpted stone",
"generationId": "generation_01...",
"creditsUsed": 4
}Image model guide
All image entries shown on Models use POST /v1/images. Copy the request above and choose the model ID below.
| Model page | API model value | Useful controls |
|---|---|---|
| Nano Banana Pro | nano-banana-pro | resolution, aspectRatio, images, numImages |
| Nano Banana 2.1 | nano-banana-2.1 | resolution, aspectRatio (incl. 8:1–1:8, auto), up to 14 images, enableWebSearch |
| Nano Banana 2 | nano-banana-2 | resolution, aspectRatio, images, numImages |
| GPT Image 2.5 | gpt-image-2.5 or gpt-image-2.5-sunburst | quality (low–max), resolution, up to 16 images, transparentBackground |
| Midjourney V8 | midjourney-v8 | 4 images per run, resolution (1K or 2K HD), aspectRatio, images, stylize, chaos, weird, seed, styleReferenceUrl |
| GPT Image 2 | gpt-image-2 | quality, resolution, images, outputFormat |
| Seedream 5 | seedream-5.0-pro or seedream-5.0-lite | resolution, aspectRatio, images |
| Seedream V5 Pro Unrestricted | seedream-5.0-pro | Use the supported Pro API route for this catalog entry |
const response = await fetch("https://api.imageat.com/v1/images", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.IMAGEAT_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "gpt-image-2.5", // replace with any image model ID above
prompt: "Editorial product photograph, soft studio light",
resolution: "1K",
quality: "low",
aspectRatio: "1:1",
numImages: 1
})
})
const result = await response.json()Image request parameters
| Parameter | Default | Description |
|---|---|---|
| model | nano-banana-pro | nano-banana-pro, nano-banana-2.1, nano-banana-2, gpt-image-2.5, gpt-image-2.5-sunburst, midjourney-v8, gpt-image-2, seedream-5.0-pro, or seedream-5.0-lite |
| prompt | required | Generation or editing instructions |
| images | — | Optional public URLs or base64 data URLs, each under 10 MB |
| aspectRatio | 1:1 | 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, or 2:3. GPT Image 2.5 renders it as exact pixels and squares off anything it cannot match. Nano Banana 2.1 also takes 21:9, 5:4, 4:5, 4:1, 1:4, 8:1, 1:8, and auto |
| resolution | 1K | 1K, 2K, or 4K |
| quality | medium | GPT Image 2: low, medium, or high. GPT Image 2.5 adds xhigh and max |
| transparentBackground | false | GPT Image 2.5 only: returns a cut-out with no background, in png or webp |
| outputFormat | png | png, jpeg, or webp |
| enableWebSearch | false | Nano Banana models: ground the image in a live web search (Nano Banana 2.1 adds $0.03 per request) |
| numImages | 1 | Generate 1–4 outputs. Ignored by midjourney-v8, which always returns 4 |
The API keeps provider routing behind imageat. Your application uses the same model IDs, authentication, credits, and response shape.
Midjourney V8
Use midjourney-v8 (Midjourney V8.2) on both POST /v1/images and POST /v1/videos. No Midjourney subscription is needed. Every run returns 4 outputs, and the price covers all four, so read urls rather than url.
- Images ($0.18 per run of 4, $0.26 at 2K HD): text-to-image, or pass an image in
images[0]to re-imagine it. The request is synchronous and takes about two minutes.numImagesis ignored. - Video ($0.18 per run of 4 at 480p, $0.52 at 720p): image-to-video only. Each run makes four 5-second clips from
imageUrl.
| Parameter | Applies to | Description |
|---|---|---|
| prompt | image (required), video (optional) | Up to 1,024 characters |
| aspectRatio | image | 1:1, 9:16, 16:9, 4:3, 3:4, 2:3, 3:2, 9:21, or 21:9. Other ratios snap to the nearest one |
| resolution | image | 1K, or 2K for native 2K HD |
| images | image | Optional. images[0] is re-imagined (image-to-image); images[1] is used as a style reference |
| styleReferenceUrl | image | Optional public URL of a style reference image (same as images[1]) |
| stylize / chaos / weird | image | Optional, 0–1000 / 0–100 / 0–3000 |
| seed | image | Optional non-negative integer |
| imageUrl | video (required) | Public URL of the image to animate |
| resolution | video | 480p or 720p |
| motion | video | low or high |
curl -X POST "https://api.imageat.com/v1/images" \
-H "Authorization: Bearer $IMAGEAT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "midjourney-v8",
"prompt": "A lighthouse on a basalt cliff at dusk, painterly, volumetric fog",
"aspectRatio": "16:9",
"resolution": "1K",
"stylize": 250
}'{
"url": "https://cdn.imageat.com/generated/mj-1.png",
"urls": [
"https://cdn.imageat.com/generated/mj-1.png",
"https://cdn.imageat.com/generated/mj-2.png",
"https://cdn.imageat.com/generated/mj-3.png",
"https://cdn.imageat.com/generated/mj-4.png"
],
"prompt": "A lighthouse on a basalt cliff at dusk, painterly, volumetric fog",
"generationId": "generation_01...",
"generationIds": ["generation_01...", "generation_02...", "generation_03...", "generation_04..."]
}curl -X POST "https://api.imageat.com/v1/videos" \
-H "Authorization: Bearer $IMAGEAT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "midjourney-v8",
"imageUrl": "https://example.com/still.jpg",
"prompt": "Slow push-in, fog drifting past the lighthouse",
"resolution": "480p",
"motion": "low"
}'The video request returns taskId and generationId like every other video model. When GET /v1/videos/status reports completed, urls holds all four clips (url is the first). Webhook payloads carry urls too.
Video generation models
Every video model shown on the Models page uses the same asynchronous endpoint and polling flow. Choose the model ID, then supply the controls supported by that model.
| Model | Model ID | Price | Guide |
|---|---|---|---|
| MiniMax H3 Max 5–15s · 480p/768p | minimax-h3-max | From $0.25 | Text, image, or first/last-frame video |
| Seedance 2.5 4–30s · 480p/720p | seedance25 | From $0.83 | Text, image, reference, or frame-controlled video |
| Midjourney V8 4 × 5s · 480p/720p | midjourney-v8 | From $0.18 | Image-to-video, 4 clips per run |
| Pixverse V6 1–15s · up to 1080p | pixverse | From $0.09/sec | Text/image video with optional audio |
minimax-h3-max for 5–15 second text, image, and first/last-frame generation; seedance25 for 4–30 seconds and reference inputs; midjourney-v8 to animate one image into four 5-second clips; or pixverse for flexible 1–15 second video with optional audio.MiniMax H3 Max API page →Midjourney V8 model page →Pixverse V6 model page →Create a Seedance 2.5 video
POST /v1/videos
The endpoint accepts JSON and returns a task ID. Keep the API key on your server and poll the status endpoint until a CDN video URL is returned.
curl -X POST "https://api.imageat.com/v1/videos" -H "Authorization: Bearer $IMAGEAT_API_KEY" -H "Content-Type: application/json" -d '{
"model": "seedance25",
"providerVariant": "more",
"prompt": "A paper airplane glides through a softly lit studio",
"duration": "5s",
"resolution": "720p",
"aspectRatio": "adaptive",
"generateAudio": true,
"outputFormat": "mp4",
"watermark": false
}'{
"status": "pending",
"taskId": "2750591",
"generationId": "a45ooNh1FBLgv6bjy7My",
"prompt": "A paper airplane glides through a softly lit studio"
}For image-to-video, send imageUrl. For a directed transition, send both firstFrameUrl and lastFrameUrl.
Video model request examples
Change only the model-specific fields shown here. Every request returns either a completed URL or the taskId/generationId pair used by the polling example below.
{
"model": "minimax-h3-max",
"prompt": "A slow cinematic dolly through a sunlit garden",
"duration": "5s",
"resolution": "480p",
"aspectRatio": "16:9",
"generateAudio": false
}{
"model": "seedance25",
"providerVariant": "more",
"prompt": "A paper airplane glides through a softly lit studio",
"duration": "5s",
"resolution": "720p",
"aspectRatio": "adaptive",
"generateAudio": true
}{
"model": "midjourney-v8",
"imageUrl": "https://example.com/still.jpg",
"prompt": "Slow push-in, fog drifting past the lighthouse",
"resolution": "480p",
"motion": "low"
}{
"model": "pixverse",
"prompt": "Neon reflections ripple across a rainy city street",
"duration": "5s",
"resolution": "720p",
"aspectRatio": "16:9",
"generateAudio": false
}Seedance 2.5 request parameters
| Parameter | Default | Description |
|---|---|---|
| model | required | Use seedance25 |
| providerVariant | standard | Use more for this Seedance 2.5 endpoint |
| prompt | required | Scene, motion, camera, style, and audio direction |
| imageUrl | — | Optional first frame for image-to-video |
| firstFrameUrl / lastFrameUrl | — | Send both URLs for first-and-last-frame generation |
| duration | 5s | Whole seconds from 4s through 30s |
| resolution | 720p | 480p or 720p |
| aspectRatio | adaptive | adaptive, 16:9, 9:16, 4:3, 3:4, 1:1, or 21:9 |
| generateAudio | true | Generate synchronized audio; no additional credit surcharge |
| outputFormat | mp4 | mp4 for broad compatibility or mov for compatible post-production workflows |
| watermark | false | Optional boolean watermark control |
Poll video status
GET /v1/videos/status?taskId={taskId}&generationId={generationId}
Poll every 5–10 seconds while status is pending. Reuse the same Bearer API key used to create the generation.
curl "https://api.imageat.com/v1/videos/status?taskId=2750591&generationId=a45ooNh1FBLgv6bjy7My" -H "Authorization: Bearer $IMAGEAT_API_KEY"
{
"status": "completed",
"url": "https://cdn.imageat.com/generated/video.mp4"
}A failed task returns { "status": "failed", "error": "..." }. Failed provider generations are handled by the platform's refund workflow.
Cancel an unfinished task with POST /v1/videos/cancel and a JSON body containing both taskId and generationId. Ownership is verified before the provider task is cancelled and unused balance is refunded.
Pass a public HTTPS URL as webhook_url when creating a video to receive video.completed or video.failed. Optionally pass a 16–256 character webhook_secret; it is encrypted at rest and deliveries include an HMAC-SHA256 x-imageat-signature.
New · OpenAI
GPT-6 Astra
Use openai/gpt-6-astra for long-context reasoning, image input, web search, and native tool-calling workflows.
curl -X POST "https://api.imageat.com/v1/chat/completions" \
-H "Authorization: Bearer $IMAGEAT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"openai/gpt-6-astra","messages":[{"role":"user","content":"Plan this agent workflow"}],"reasoning":"high","verbosity":"medium","web_search":true}'Astra also accepts OpenAI-format tools, tool_choice, parallel_tool_calls, and image URL content parts. Maximum output is currently capped at 4,000 tokens by imageat.
Chat completions
Generate chat and reasoning responses through an OpenAI-compatible endpoint using the same imageat API key. One endpoint serves every LLM in the catalog — switch models by changing the model field.
Flagship uncensored model: qwen/qwen3.8-27b-uncensored · Context window: 262,144 tokens · Output limit: 4,000 tokens
The same advanced thinking and sampling controls are supported by qwen/qwen3-8-27b, qwen/qwen3-8-27b-obliterated, and unsloth/qwen3-8-flash-next-gguf.
| Model ID | Name | Provider |
|---|---|---|
| qwen/qwen3.8-27b-uncensored | Qwen 3.8 27B Uncensored | Qwen |
| openai/gpt-6-astra | GPT-6 Astra | OpenAI |
| unsloth/qwen3-8-flash-next-gguf | Qwen 3.8 Flash Next GGUF | Unsloth |
| qwen/qwen3-8-27b-obliterated | Qwen 3.8 27B Obliterated | Qwen |
| qwen/qwen3-8-27b | Qwen 3.8 27B | Qwen |
| google/gemini-3.8-flash | Gemini 3.8 Flash | |
| google/gemini-3.7-flash | Gemini 3.7 Flash | |
| openai/gpt-5-6-sol | GPT 5.6 Sol | OpenAI |
| openai/gpt-5-6-terra | GPT 5.6 Terra | OpenAI |
| openai/gpt-5-6-luna | GPT 5.6 Luna | OpenAI |
| xai/grok-4-5 | Grok 4.5 | xAI |
| zhipu/glm-4.7-flash | GLM 4.7 Flash | Zhipu AI |
| openai/gpt-oss-20b | GPT-OSS 20B | OpenAI |
| claude/sonnet-5 | Claude Sonnet 5 | Anthropic |
| claude/opus-5 | Claude Opus 5 | Anthropic |
A request for an ID outside this list is rejected with 400 Unsupported model, and the response lists the accepted IDs.
Create a chat completion
POST /v1/chat/completions
The request follows the familiar OpenAI chat-completions shape. Set stream to true for a text/event-stream response, or omit it for a single JSON completion.
curl -X POST "https://api.imageat.com/v1/chat/completions" \
-H "Authorization: Bearer $IMAGEAT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen/qwen3.8-27b-uncensored",
"messages": [
{"role": "system", "content": "You are a concise product strategist."},
{"role": "user", "content": "Suggest three retention features for Imageat."}
],
"enable_thinking": false,
"temperature": 0.7,
"max_tokens": 500
}'Long or thinking-enabled requests can take several minutes. Keep the HTTP connection open until the final completion is returned.
OpenAI-compatible clients
Any tool that speaks the OpenAI API — opencode, Cline, Continue, the OpenAI SDKs, the Vercel AI SDK — works by pointing its base URL at https://api.imageat.com/v1 and using the imageat key as the API key. Include the /v1: https://api.imageat.com on its own returns 404.
export OPENAI_BASE_URL="https://api.imageat.com/v1" export OPENAI_API_KEY="$IMAGEAT_API_KEY"
GET /v1/models lists every model ID this endpoint accepts.
POST /v1/responses supports the newer Responses API shape, including instructions, input items, function tools, structured function-call output, and Responses-style SSE events. This is useful for Codex-style agents and SDKs that prefer Responses over Chat Completions.
curl -X POST "https://api.imageat.com/v1/responses" \
-H "Authorization: Bearer $IMAGEAT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen/qwen3.8-27b-uncensored",
"input": "Give me a two-line launch checklist",
"stream": true
}'Streaming responses are OpenAI-style chat.completion.chunk events terminated by data: [DONE]. The model runs as a batch task, so the text is buffered until it finishes and then streamed out; the connection is held open with SSE comment pings in the meantime.
Agent clients may send OpenAI-format tools and tool_choice. Function selections are returned as structured message.tool_calls (or streamed delta.tool_calls) with finish_reason: "tool_calls"; send the tool result back in a role: "tool" message to continue the loop.
For Responses API streams, consume typed events such as response.output_text.delta, response.function_call_arguments.done, and response.completed. To continue a tool loop, include the prior function_call and matching function_call_output items in the next request's input.
Stored Responses support previous_response_id, GET /v1/responses/{response_id}, DELETE /v1/responses/{response_id}, and POST /v1/responses/{response_id}/cancel. Set store: false for stateless requests.
Production reliability
Send a unique Idempotency-Key on non-streaming image, video, chat, and Responses requests. Keys are scoped to the credential and endpoint, retained for 24 hours, and replay the original response without charging twice.
Every v1 response includes x-request-id. You may supply x-client-request-id for correlation. Rate-limit responses include Retry-After and rate-limit headers.
Errors use an OpenAI-style { error: { message, type, param, code } } envelope on the new lifecycle and reliability paths. Token usage in Responses includes estimated input/output counts when the upstream provider does not expose tokenizer totals.
Agent client configuration
OpenCode can use imageat as its model provider, while Claude, Cursor, VS Code/Copilot, Cline, Continue, and Roo Code can connect to the remote MCP server at https://mcp.imageat.com/mcp.
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"imageat": {
"npm": "@ai-sdk/openai-compatible",
"options": {
"baseURL": "https://api.imageat.com/v1",
"apiKey": "{env:IMAGEAT_API_KEY}"
},
"models": {
"qwen/qwen3.8-27b-uncensored": { "name": "Qwen 3.8" }
}
}
},
"model": "imageat/qwen/qwen3.8-27b-uncensored"
}{
"servers": {
"imageat": {
"type": "http",
"url": "https://mcp.imageat.com/mcp"
}
}
}MCP 0.4 exposes typed tool results, safety annotations, model/account/recent-generation resources, reusable prompts, and an experimental imageat_generate_video_task lifecycle alongside the backwards-compatible video status tool.
Request parameters
| Parameter | Default | Description |
|---|---|---|
| model | Qwen model ID | Any ID returned by GET /v1/models |
| messages | required | System, user, and assistant messages |
| stream | false | true returns OpenAI-style server-sent events |
| tools | — | OpenAI-format function definitions available to the model |
| tool_choice | auto | auto, none, required, or a specific function |
| enable_thinking | true | Deeper reasoning or shorter direct answers |
| temperature | 0.7 | Output randomness |
| top_p / top_k | 0.95 / 20 | Probability sampling controls |
| max_tokens | 1000 | Maximum output tokens; capped at 4,000 |
| min_tokens | 0 | Minimum output-token target |
| repetition_penalty | 1.0 | Reduces repeated phrases and loops |
| length_penalty | 1.0 | Biases toward shorter or longer output |
| stop | — | String or array of stop sequences |
| seed | 123456 | Optional repeatability seed |
| quantization / do_sample | true / true | Efficiency and sampling toggles |
| user / session_id | — | Optional conversation identifiers |
model, messages, max_tokens, and stream apply to every model. The sampling controls below them — enable_thinking, temperature, top_p, top_k, the penalties, stop, seed, quantization, and do_sample — are available on the Qwen 3.8 family; other catalog models ignore them.
Response and credit billing
{
"id": "chatcmpl_2747897",
"object": "chat.completion",
"model": "qwen/qwen3.8-27b-uncensored",
"choices": [{
"index": 0,
"message": { "role": "assistant", "content": "..." },
"finish_reason": "stop"
}],
"credits_used": 2,
"billing": {
"reserved_credits": 3,
"provider_cost_usd": 0.0324,
"elapsed_seconds": 54
}
}Read the generated text from choices[0].message.content.
Qwen 3.8 27B Uncensored reserves three credits and settles at 1–3 credits. The other Qwen 3.8 and catalog models reserve ten and settle at 1–10 credits. Unused reserved credits are returned automatically, and failed requests receive a full refund.
LLM errors include 400 for invalid messages or an unsupported model, 402 for insufficient balance, 429 for rate limits, and 502 when the provider request fails.
Run lifecycle
A run moves through these states:
queued— accepted, waiting for a workerrunning— worker executing nodescompleted— all outputs readyfailed— one or more nodes failed; checkerrorcancelled— cancelled before completion
Credits are reserved at run creation and settled (refund of unused portion) once the run completes or fails. The final response includes credits_used.
Create a run
POST /v1/workflows/{workflow_id}/runs — start a run of a published workflow.
POST https://api.imageat.com/v1/workflows/wf_abc123/runs
Authorization: Bearer iat_live_...
Content-Type: application/json
Idempotency-Key: 8f3b... (optional)
{
"nodes": [],
"edges": [],
"webhook": {
"url": "https://your-app.com/webhook/imageat",
"secret": "whsec_..."
}
}If you pass empty nodes/edges, the saved (published) workflow graph is used. Pass them to override inputs (e.g. a different prompt) per-run.
{
"run_id": "run_01HX...",
"status": "queued"
}Idempotency: send the same Idempotency-Key to safely retry a request — the same run is returned instead of creating a duplicate.
Poll a run
GET /v1/runs/{run_id}
{
"run_id": "run_01HX...",
"status": "completed",
"outputs": {
"node_output_1": {
"type": "image",
"value": "https://cdn.imageat.com/runs/run_01HX.../node_output_1.png"
}
},
"credits_used": 12,
"created_at": "2026-05-22T10:01:24Z",
"completed_at": "2026-05-22T10:01:38Z"
}Poll every 1–2 seconds while the status is queued or running. For faster feedback, use SSE.
Server-sent events (live updates)
GET /v1/runs/{run_id}/events
Returns a text/event-stream. Each event is a JSON line emitted as nodes start, finish, or the run terminates. The stream closes after run_complete or run_failed.
data: {"event":"node_start","node_id":"n1"}
data: {"event":"node_complete","node_id":"n1","output":{...}}
data: {"event":"run_complete","run_id":"run_01HX..."}Cancel a run
POST /v1/runs/{run_id}/cancel
Cancels a queued or running run. Reserved credits are refunded; already-executed node costs are kept.
{ "ok": true }Outputs & CDN URLs
Final outputs are mirrored to cdn.imageat.com so URLs are stable and fast. The path format is:
https://cdn.imageat.com/runs/{run_id}/{node_id}.{ext}Each output entry has a type describing how to consume the value:
| type | value |
|---|---|
| image | Single CDN image URL |
| images | Array of image URLs |
| video | CDN video URL (mp4) |
| text | Plain text (e.g. LLM output) |
Webhooks
Pass a webhook object on run creation to receive a signed POST when the run terminates — no polling required.
POST https://your-app.com/webhook/imageat
X-Imageat-Signature: t=1716372924,v1=sha256(...)
Content-Type: application/json
{
"event": "run_complete",
"run_id": "run_01HX...",
"status": "completed",
"outputs": { ... },
"credits_used": 12
}Verify X-Imageat-Signature using your webhook secret: compute HMAC-SHA256 over {timestamp}.{raw_body} and compare in constant time.
Error codes
| status | meaning |
|---|---|
| 401 | Missing or invalid API key |
| 402 | Insufficient credits — response includes balance and required |
| 403 | Run belongs to a different account |
| 404 | Workflow or run not found, or workflow not published |
| 422 | Invalid request body (bad nodes/edges) |
| 500 | Internal worker error — safe to retry with the same Idempotency-Key |
Code examples
A full create → poll → read flow in three languages.
# 1. Create a run
RUN=$(curl -s -X POST https://api.imageat.com/v1/workflows/wf_abc123/runs \
-H "Authorization: Bearer $IMAGEAT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"nodes": [], "edges": []}' | jq -r .run_id)
# 2. Poll until complete
while true; do
RES=$(curl -s https://api.imageat.com/v1/runs/$RUN \
-H "Authorization: Bearer $IMAGEAT_API_KEY")
STATUS=$(echo "$RES" | jq -r .status)
[ "$STATUS" = "completed" ] && echo "$RES" | jq .outputs && break
[ "$STATUS" = "failed" ] && echo "$RES" | jq . && exit 1
sleep 2
doneconst API_KEY = process.env.IMAGEAT_API_KEY!;
const BASE = "https://api.imageat.com/v1";
async function runWorkflow(workflowId: string) {
const create = await fetch(`${BASE}/workflows/${workflowId}/runs`, {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ nodes: [], edges: [] }),
});
if (!create.ok) throw new Error(`create failed: ${create.status}`);
const { run_id } = await create.json();
while (true) {
await new Promise((r) => setTimeout(r, 1500));
const poll = await fetch(`${BASE}/runs/${run_id}`, {
headers: { Authorization: `Bearer ${API_KEY}` },
});
const data = await poll.json();
if (data.status === "completed") return data;
if (data.status === "failed") throw new Error(data.error);
}
}
const result = await runWorkflow("wf_abc123");
console.log(result.outputs, result.credits_used);import os, time, requests
API_KEY = os.environ["IMAGEAT_API_KEY"]
BASE = "https://api.imageat.com/v1"
H = {"Authorization": f"Bearer {API_KEY}"}
def run_workflow(workflow_id: str) -> dict:
r = requests.post(
f"{BASE}/workflows/{workflow_id}/runs",
headers={**H, "Content-Type": "application/json"},
json={"nodes": [], "edges": []},
)
r.raise_for_status()
run_id = r.json()["run_id"]
while True:
time.sleep(1.5)
data = requests.get(f"{BASE}/runs/{run_id}", headers=H).json()
if data["status"] == "completed":
return data
if data["status"] == "failed":
raise RuntimeError(data.get("error", "run failed"))
result = run_workflow("wf_abc123")
print(result["outputs"], result["credits_used"])imageat MCP Server
Use imageat directly from AI clients like Claude Desktop, Cursor, and any other tool that speaks the Model Context Protocol — no code required.
Overview
The @imageat/mcp package is a Model Context Protocol (MCP) server. Once connected, your AI client gains tools to generate images, generate video, and run every imageat edit feature — all billed against your account credits. Edit tools are discovered live, so new features appear automatically.
Step-by-step setup for Claude, ChatGPT, Cursor, OpenClaw, Hermes, and other clients: imageat MCP setup guide.
Published on npm: npmjs.com/package/@imageat/mcp
Grok Bot & terminal agents
Grok Bot: add a custom remote HTTPS MCP server named imageat at https://mcp.imageat.com/mcp, then complete the imageat sign-in and authorization. Ask the Bot to discover tools and check your balance before your first generation.
CLI: install Node.js 18+ and run npm i -g @imageat/mcp. Register imageat-mcp as a stdio server in your terminal agent's MCP settings, with your Projects API key in IMAGEAT_API_KEY. Restart or reload the agent to discover tools.
The command is an MCP server, so your agent manages its input and output. Authentication uses the API key; there is no separate imageat CLI login command. Built-in MCP workflow prompts include product visuals, image animation, and social campaigns.
read -r -s IMAGEAT_API_KEY
export IMAGEAT_API_KEY
curl -X POST "https://api.imageat.com/v1/images" \
-H "Authorization: Bearer $IMAGEAT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"seedream-5.0-pro","prompt":"A cinematic product photograph","resolution":"2K","numImages":1}'
unset IMAGEAT_API_KEYThis Bash/zsh example reads your key without echoing it, generates one paid image, and returns its URL. For videos, use the video API examples in this guide or the MCP video tools.
Install
You only need Node.js 18+ and an API key from your Projects page. Add the server to your client's MCP config:
{
"mcpServers": {
"imageat": {
"command": "npx",
"args": ["-y", "@imageat/mcp"],
"env": {
"IMAGEAT_API_KEY": "iat_live_xxxxxxxxxxxx"
}
}
}
}On macOS this file lives at ~/Library/Application Support/Claude/claude_desktop_config.json. Restart the client after editing. The imageat tools will appear in the tools menu.
| env var | notes |
|---|---|
| IMAGEAT_API_KEY | Required. Your iat_live_ key. |
| IMAGEAT_BASE_URL | Optional. Defaults to https://imageat.com. |
claude.ai & ChatGPT (remote)
The npx setup above is a local process, so it works in desktop apps (Claude Desktop, Cursor). Browser clients like claude.ai and ChatGPT instead connect to a remote MCP endpoint over Streamable HTTP:
https://mcp.imageat.com/mcp
| Client | How to add |
|---|---|
| claude.ai | Settings → Connectors → Add custom connector → paste the URL above. |
| ChatGPT | Connectors / Developer mode → add server → paste the URL above. |
When the client asks for the connector's authorization, provide your iat_live_ key — it's sent as a Bearer token and scoped to your account's credits. Same tools, same billing as the desktop setup.
Tools
The server exposes these tools to the connected client:
| tool | what it does |
|---|---|
| imageat_generate_image | Text-to-image / image-to-image. Returns CDN image URL(s). |
| imageat_generate_video | Text-to-video / image-to-video. Returns a CDN mp4 URL. |
| imageat_check_credits | Spendable balance — subscription credits and prepaid API balance. |
| imageat_edit_* | One tool per edit feature — remove background, object eraser, relight, virtual try-on, city teleport, inpaint, and more. Fetched live, so new features appear automatically. |
Same auth and billing as the REST API — every call is metered against the API key's account, and errors return clear messages (e.g. 402 with your balance when out of credits).
