Keytween

Reference

Jobs, waiting and limits

Every generation is a job on a shared render queue. One GPU renders one job at a time. Accounts take turns: when several accounts have work waiting, the next job comes from the account served least recently, and each account's own jobs run in the order it submitted them. A long batch from one account or agent therefore never blocks everyone else, and how long you wait depends on the job itself and on what is ahead of it.

Lifecycle #

Status Meaning Useful fields
queued Accepted and charged, waiting for the renderer queue_position (1 = next), eta_seconds, phase
running Rendering progress (0 to 1), phase (what is happening now), eta_seconds
succeeded Finished outputs with download links
failed Did not finish; refunded in full error, refunded
cancelled Stopped by you or interrupted; refunded in full refunded

succeeded, failed and cancelled are final.

Typical times #

Job Render time once it starts
Image about 10 seconds at 1 MP, 25 at 2 MP, a minute at 4 MP; more with references
Edit about 15 seconds at 1 MP, 40 at 2 MP; more with references
Video 2 to 3 minutes; longer and larger clips take longer

The first image after a video takes longer while the image models load, so a short run of image jobs is kept together before switching back to video. get_service_status (REST: GET /meta) reports whether rendering is online, whether new work is being accepted, how many jobs are queued across the service and the estimated wait. eta_seconds on a job is estimated from its size and length, corrected by recent measured render times, plus the jobs ahead of it; treat it as an estimate.

A job that runs far longer than its estimate is stopped and refunded, so a stuck render cannot hold the GPU.

Waiting over MCP #

No tool call needs to stay open for the whole render.

  1. generate_image, edit_image and generate_video submit the job and then wait up to wait_seconds (default 45, maximum 300, 0 to return at once).
  2. They return the job as it stands. If it finished, the outputs are there. If not, status is queued or running and next tells you to wait.
  3. wait_for_job waits again for up to timeout_seconds. Call it until the status is final. get_job checks without waiting.
generate_video ...            -> job J, status "running", progress 0.31, eta_seconds 95
wait_for_job  job_id J        -> status "running", progress 0.74, eta_seconds 40
wait_for_job  job_id J        -> status "succeeded", outputs [...]

While a call is open, the server sends MCP progress notifications (to clients that pass a progress token) and keep-alive frames, so connections through proxies stay up.

Choosing a wait. The defaults stay under the 60-second tool timeout many clients enforce. If your client allows longer calls, use eta_seconds plus a margin, up to 300. See the timeout table in Connect your agent.

If a call times out on the client side, the job is unaffected: it keeps its place and its credits stay reserved. Do not submit it again. Find it with list_jobs (active_only: true) and resume with wait_for_job.

There is no automatic de-duplication. Submitting the same request twice makes, and charges for, two jobs.

Waiting over REST #

POST /jobs returns 202 with the job at once. Then either poll GET /jobs/:id every few seconds, or hold one GET /events connection (Server-Sent Events) and react to job events. See the REST API reference.

Cancelling #

cancel_job (REST: POST /jobs/:id/cancel) stops a queued or running job and refunds it. A running render stops within a few seconds.

Limits #

Limit Value
Generations queued or running at once, per account reported by get_account as concurrent_limit (3 by default)
Work waiting on the shared queue new jobs are refused while the queue holds more than about 30 minutes of work (less for trial accounts)
MCP requests 300 per minute
REST requests 600 per minute per address; job creation 30 per minute
Prompt length 4000 characters (8000 with the pro model)
References per generation 4
Upload size 25 MB per image (PNG, JPEG, WebP)
Download links from MCP valid for 1 hour; get_asset issues a new one
Upload links from MCP valid for 15 minutes

Over a limit you get 429; wait and retry. too_many_jobs clears as soon as one of your jobs finishes.

When the shared queue is full or rendering is offline, new jobs get 503 with queue_full or renderer_offline. Nothing is charged. Wait a few minutes before submitting again (check accepting_new_jobs in get_service_status); do not retry in a tight loop. Jobs that were already accepted stay queued and run when the renderer is back, or are refunded if it stays offline.

Errors #

Over MCP, a failed tool call returns isError: true with a JSON body {"error": {"code", "message", "hint"}}; the hint says what to do next. Over REST the same codes come back as {"error": {"code", "message"}} with the HTTP status shown.

Code Status Meaning
invalid_request 400 A parameter is missing or out of range; the message names it
invalid_size 400 Width and height must be given together and fit the size limits (sequence frames are smaller than standalone images)
invalid_sprite 400 Sprite size or options out of range
not_a_sprite 400 The sprite-set tools only take sprites (and, for links, sprite sheets)
sheet_too_large 400 A sprite sheet would be wider or taller than 4096 px
invalid_style_kit 400 Style kit fields out of range
style_kit_not_found 404 No such style kit on this account
too_many_style_kits 400 The account already has the maximum number of style kits
not_a_sequence 400 Frames and video need a sequence; that id is the image library
invalid_frames, clip_too_long 400 Clip length out of range for this frame size
no_start_frame 400 The step has no selected start frame yet
no_end_frame 400 First-and-last-frame video needs a selected end frame
start_fixed 400 From the second step on, the start frame is the previous take's last frame
invalid_source 400 That image cannot be edited in this way; the message says what to do instead
size_mismatch 400 The frame does not have the sequence's frame size
unknown_reference 400 An @label in the prompt is not a reference of this sequence
too_many_references 400 More than 4 references in one prompt
clip_stale 400 That take was rendered from a different start frame than the one selected
unauthenticated, invalid_api_key 401 Missing, wrong or revoked API key
insufficient_credits 402 The balance does not cover the job
forbidden, account_disabled 403 The account may not do this
project_not_found, segment_not_found, asset_not_found, job_not_found 404 No such item on this account
segment_accepted 409 The step is accepted; work on the open step or reopen it
asset_in_use, asset_locked 409 The item is selected or belongs to an accepted step
jobs_active 409 Wait for or cancel the running generations first
job_finished 409 The job already finished and cannot be cancelled
too_many_jobs 429 The concurrency limit is reached
queue_full 503 The shared render queue is at capacity; nothing was charged
renderer_offline 503 Rendering is offline; nothing was charged

A job that fails while rendering reports a general message (The render failed on our side. Your credits were refunded.). It is safe to submit it again; if failures repeat, check get_service_status.

All docs