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 usage is billed in imageat credits. 1 credit = $0.10. The prices below show the minimum supported configuration; the final charge increases with resolution, quality, duration, or output count.
| Model | Starts at | Minimum configuration |
|---|---|---|
| nano-banana-pro | 8 credits · $0.80 | 1 image · 1K |
| nano-banana-2 | 4 credits · $0.40 | 1 image · 1K |
| gpt-image-2 | 2 credits · $0.20 | 1 image · low quality · 1K |
| seedream-5.0-pro | 3 credits · $0.30 | 1 image · 1K |
| seedance25 | 16 credits · $1.60 | 4 seconds · 480p |
| pixverse | 3 credits/sec · $0.30 | 720p · audio off |
| qwen/qwen3.8-27b-uncensored | 1 credit · $0.10 | Short completion; final cost is usage-based |
numImages. Seedance 2.5 is 4 credits/second at 480p or 8 credits/second at 720p. Pixverse V6 is 3 credits/second at 720p and 5 at 1080p, each +1 with audio on. Qwen reserves 3 credits, then settles the completed request at 1–3 credits.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 8 credits · $0.80
nano-banana-2Nano Banana 2
Fast, cost-efficient generation for iterative creative work.
From 4 credits · $0.40
gpt-image-2GPT Image 2
Precise instruction following with low, medium, and high quality tiers.
From 2 credits · $0.20
seedream-5Seedream 5
ByteDance generation and reference-guided editing in Pro and Lite.
From 3 credits · $0.30
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 request parameters
| Parameter | Default | Description |
|---|---|---|
| model | nano-banana-pro | nano-banana-pro, nano-banana-2, 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 |
| resolution | 1K | 1K, 2K, or 4K |
| quality | medium | GPT Image 2 only: low, medium, or high |
| outputFormat | png | png, jpeg, or webp |
| numImages | 1 | Generate 1–4 outputs |
The API keeps provider routing behind imageat. Your application uses the same model IDs, authentication, credits, and response shape.
Seedance 2.5
Generate 4–30 second videos from text, a first-frame image, or first and last frames. Choose 480p or 720p output with optional synchronized audio.
Model ID: seedance25 · Endpoint: POST /v1/videos · From 16 credits ($1.60) at 4s / 480p · Asynchronous output
POST /v1/videos also accepts minimax-h3-max for 5–15 second text, image, and first/last-frame generation at 480p or 768p, plus pixverse for Pixverse V6. The request and polling flow below is identical; only the model-specific inputs change.MiniMax H3 Max API 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.
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.
Qwen 3.8 27B Uncensored
Generate long-context chat and reasoning responses through an OpenAI-compatible endpoint using the same imageat API key.
Model ID: qwen/qwen3.8-27b-uncensored · Context window: 262,144 tokens · Output limit: 4,000 tokens
Create a chat completion
POST /v1/chat/completions
The request follows the familiar OpenAI chat-completions shape. Streaming is not currently supported, so set stream to false or omit it.
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.
Qwen request parameters
| Parameter | Default | Description |
|---|---|---|
| model | Qwen model ID | Must be qwen/qwen3.8-27b-uncensored |
| messages | required | System, user, and assistant messages |
| 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 |
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.
Three credits are reserved when the request starts. The completed request is charged 1–3 credits from its actual processing cost, and unused reserved credits are automatically returned. Failed requests receive a full refund.
Qwen-specific errors include 400 for invalid messages or unsupported streaming, 402 for fewer than three available credits, 429 for rate limits, and 502 when the model 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
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 | Current credit 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).
