GPU Forge

Ready programs

GPU Forge packages, runs and updates a set of open AI models as ready programs. There is nothing to install and no model to download. You can use them in two ways:

  • As jobs (POST /v1/jobs): one request, one result, pay per render second. See Jobs.
  • On your own machine: add the program to your account, start a machine and call the program's own API, paying for the machine per second.
ProgramWhat it doesJob routes
FLUX 3 KleinMakes images from a prompt, edits images, combines up to 4 reference images/v1/generate, /v1/edit
Krea 2Makes images from a prompt (with an optional prompt writer), edits images/v1/generate, /v1/edit
LTX-2.5Video with its own soundtrack, from a prompt or from a first frame; lips can follow speech you supply/v1/jobs/text-to-video, /v1/jobs/image-to-video
MiniMax H3Video with sound from a prompt or frames; a talking person from one photo and your words; draft and full quality/v1/jobs/text-to-video, /v1/jobs/image-to-video, /v1/jobs/talking-video

The catalog is the source of truth for which routes are sold as jobs: always read job_routes from GET /v1/catalog.

Rules for every image program

  • Every image carries an invisible GPU Forge mark, hidden in the pixels and signed in the file.
  • Images of children are never made. A request that asks for one is refused (422).
  • Results are generated by AI and may be inaccurate or unexpected; check them before you rely on them.
  • Use is subject to the Terms of Service (acceptable use).

The catalog

HTTP
GET /v1/catalog
Shell
curl -s "https://api.gpuforge.io/v1/catalog" -H "Authorization: Bearer $GF_KEY"

Returns {"programs": [...]}. Each program:

FieldDescription
capability_idThe program id. Use it as program in a job, and in POST /v1/catalog/{program_id}/add
nameShort name
titleDisplay title
summaryWhat it does
versionThe current version. New versions reach your copy by themselves
min_vram_gbGPU memory the program needs per card
max_price_per_hourThe price limit a new copy of the program starts with (you can change it on your copy)
avg_price_per_hourWhat one hour of a machine for this program usually costs you now: the middle of the cheapest machines that fit. Jobs are priced from this. null when nothing fits right now
job_routesThe routes you can run as jobs. Empty = machine use only
parked_machinesParked machines kept for you on a new copy (always 0; parking is your choice)
addedThe id of your copy of this program, or null if you have not added it
how_to_useA one-line reminder of the machine flow

Using a program on your own machine

  1. Add it to your account (once):

    Shell
    curl -s -X POST "https://api.gpuforge.io/v1/catalog/<program id>/add" \
     -H "Authorization: Bearer $GF_KEY" -H "Content-Type: application/json" -d '{}'

    201 returns your copy's capability_id and a program key (gf_api_key, shown once). Adding the same program twice answers 409 with the id of the copy you already have.

  2. Start a machine: POST /v1/capabilities/{your copy id}/deploy (or /scale with {"desired_pods": 1}). A parked machine of the program is woken first if one is free. See Machines.
  3. Wait for capability_state: ready on GET /v1/fleet/{pod_id}. capability_url is the machine's address.
  4. Read the program's guide: GET <capability_url>/v1 with Authorization: Bearer <program key>. Every request to the program needs that header (401 without it).
  5. Stop it: POST /v1/fleet/{pod_id}/release or /park.

What you can change on your copy: its settings (idle_ttl_seconds, max_price_per_hour, surge_price_per_hour, daily_budget_usd, interruptible, only_gpus, excluded_gpus, min_gpu_family, idle_by, price_reduction), active, dormant_pods, and the program key (secrets.env.GF_API_KEY). The program itself (its files, commands and settings inside) stays ours and is updated by us: reading your copy shows those parts empty, and a machine of a copy cannot be started with your own start command, image, ports or environment. There is no SSH into machines of ready programs.

Good to know:

  • Nothing is kept between starts. Each start or wake begins with an empty working folder. Upload your inputs again after every start or wake, and download each result as soon as it is made.
  • For a minute or so after ready, a video program may report "machine": "warming" on GET /v1/status; the first request waits a little.
  • For machines running our ready programs, the program's output is kept for 30 days: GET /v1/fleet/{pod_id}/output?since=&limit= (1–2000, default 200).

FLUX 3 Klein (images)

Makes images from a prompt, edits images, and combines up to 4 reference images. The prompt goes to the image model exactly as written; it works best in English, as one full description: the medium ("Full-color photograph, ..."), the scene, light and camera, then each subject with concrete colors and materials.

POST /v1/generate: an image from a prompt

FieldRequiredDescription
promptyesWhat the image shows, up to 6000 characters. Words that must appear in the image go in double quotes. With references, say what comes from each by order ("the jacket from the second image")
reference_imagesno0–4 images to combine, each base64 (JPEG, PNG or WebP, up to 20 MB)
width, heightnoBoth or neither. 256–2048, rounded to multiples of 16, at most 4.2 megapixels. Default 832 × 1216
seednoInteger

POST /v1/edit: change an image

FieldRequiredDescription
imageyesThe image to edit, base64
promptyesOne instruction that states the end result and ends with what stays the same, e.g. "Change the sky to a sunset with warm orange light. Keep the buildings and the street unchanged."
reference_imagesno0–3 more images to take a person, look or object from (the image to edit counts as the first image)
width, heightnoDefault: the input image's shape at about 1 megapixel
seednoInteger

Response (both routes, 200)

JSON
{"image": "<base64 JPEG>", "mime_type": "image/jpeg", "width": 832, "height": 1216, "seed": 7, "seconds": {"total": 3.1}}

seconds.total is the render time; jobs are billed on it. Other fields may be present; ignore fields you do not use.

Errors

400 invalid input (the message names the field) · 401 missing or wrong program key · 422 refused (the message says why) · 503 busy (see Retry-After) · 500 the render failed.

On your own machine, one image renders at a time and up to 8 wait in line. A warm machine makes an image in a few seconds.


Krea 2 (images)

Makes images from a prompt, and edits images. By default a prompt writer first turns your prompt into a full description; turn it off to send your prompt to the image model exactly as written.

POST /v1/generate: an image from a prompt

FieldRequiredDescription
promptyesWhat the image shows, in any language, up to 6000 characters. Words that must appear in the image go in double quotes
reference_imagesno0–2 base64 images (JPEG, PNG or WebP, up to 20 MB). One image: the person or style to keep (an image with a face is cropped to the head first, so only the face and hair carry over). Two images: two references. None: plain text-to-image
width, heightnoBoth or neither. 512–2048, rounded to multiples of 16, at most 2.4 megapixels. Default 832 × 1216
seednoInteger
charactersnoUp to 4 people by name: {"name", "gender" (female, male or transgender), "looks", "clothes", "reference" (1 or 2: which reference image shows them)}. Then use their names in the prompt
cameranoauto (default), fixed, selfie or mirror
stylenophoto (default), anime or stylized_3d
place, time_of_daynoShort text
enhance_promptnotrue (default): the prompt writer expands your prompt first. false: the prompt goes to the image model as written (best in English, as a full description; for an edit, describe the result). With false, characters, camera, style, place, time_of_day, image_description and image_camera are refused (400): write them into the prompt

POST /v1/edit: change an image

FieldRequiredDescription
imageyesThe image to edit, base64
promptyesThe change, e.g. "make it sunset" or "she stands up and stretches"
reference_imagenoA second image to take a person, look or object from
width, heightnoDefault: the input image's shape at about 1 megapixel
image_descriptionnoWhat the image to edit shows; helps keep the rest of it the same
image_cameranoHow the image to edit was taken: fixed, selfie or mirror
seed, enhance_prompt, characters, camera, stylenoAs above

Response (both routes, 200)

JSON
{"image": "<base64 JPEG>", "mime_type": "image/jpeg", "width": 832, "height": 1216, "seed": 7, "seconds": {"total": 16.1}}

Other fields may be present; ignore fields you do not use.

Errors

400 invalid input (names the field) · 401 program key · 422 refused (the message says why, for example a prompt that cannot be drawn) · 503 busy (Retry-After) · 500 the render failed. One image renders at a time; up to 8 wait in line.

Example (on your own machine)

Shell
curl -s "<capability_url>/v1/generate" \
  -H "Authorization: Bearer $PROGRAM_KEY" -H "Content-Type: application/json" \
  -d '{"prompt": "A cyclist rides along a coastal road at golden hour, the sea on the left.", "seed": 7}' \
  | python3 -c "import sys,json,base64; open('out.jpg','wb').write(base64.b64decode(json.load(sys.stdin)['image']))"

LTX-2.5 (video with sound)

Makes 24 fps video with its own soundtrack, from a prompt alone or opening on a picture you give. If you send finished speech (audio), the lips follow it. Your prompt goes to the model exactly as written.

Job routes

RouteWhat it makes
/v1/jobs/text-to-videoA clip from the prompt alone
/v1/jobs/image-to-videoA clip that opens on first_frame

Both wait for the clip and answer with the finished video (within 580 seconds). In a job, send pictures and sounds inline, as a data: URI or plain base64.

Request fields

FieldDefaultDescription
promptrequiredWhat happens, as the model reads it (up to 8000 characters)
first_framerequired for image-to-videoThe picture the video opens on, cut to format at crop
audiononeFinished speech (from any text-to-speech or a recording), 0.3–11.2 s. The clip gets 0.5 s of quiet, then this speech; the lips follow it, and the clip is exactly that long (at least 3 s)
seconds53–12. Only without audio; the model then makes the whole soundtrack from the prompt
formatthe picture's shape, else 9:169:16, 16:9, 1:1, 3:4, 4:3, 2:3, 3:2, 21:9 (about 0.5 megapixels, e.g. 544 × 960)
crop{"x": 0.5, "y": 0.3}Where the frame sits on a picture of another shape (0–1 each way; 0.3 keeps faces in)
seedrandomThe same seed and request give the same video
upload_urlnoneYour own presigned PUT URL (S3, R2 or any S3-compatible store). The finished MP4 is also uploaded there

Response (200)

JSON
{"video": "<base64 MP4>", "mime_type": "video/mp4", "seed": 81213, "format": "9:16", "clip_seconds": 5.0, "render_seconds": 14.2}

With upload_url, the answer also has upload: {"status": "done", "http_status": 200, "bytes": ...} or {"status": "failed", "http_status": ..., "error": "..."}. Any error is a non-2xx answer {"error": "..."}.

Writing the prompt

  • Describe the change, not the picture. With first_frame, the first frame already shows who and where; write what happens next: the motion, the expression, the camera.
  • Speech: say the person talks in the first words ("She looks into the camera and talks warmly, ..."). The lips follow your audio.
  • Short and concrete: one or two actions per clip, in the order they happen; the camera in its own sentence ("The camera holds still." / "The camera slowly pushes in.").
  • Sound without audio: write it into the prompt ("Rain on the window, a quiet café in the background.").
  • Head-and-shoulders framing gives faces the most detail.

On your own machine

The machine also offers a queue-based API: POST /v1/text-to-video and /v1/image-to-video answer 201 with a clip id; GET /v1/clips/{id}?wait=N (up to 600 s) returns the clip with a download url; POST /v1/clips/{id}/cancel; GET /v1/clips; POST /v1/uploads/photo and /v1/uploads/audio (multipart) return a name you can use in first_frame and audio; GET /v1/status. On your own machine, pictures and sounds may also be an http(s):// URL the machine can fetch. Full details: GET <capability_url>/v1.


MiniMax H3 (video with sound)

Makes 24 fps video with its own soundtrack. It can open on a picture, end on a picture, follow reference pictures and voice samples, and make a person in a photo say your words in a chosen voice. Every clip has two qualities: a fast draft for checking, and hq for delivery.

Job routes

RouteWhat it makes
/v1/jobs/talking-videoThe person in a photo says your words to the camera
/v1/jobs/text-to-videoA clip from the prompt alone
/v1/jobs/image-to-videoA clip that opens on first_frame and/or ends on last_frame

Each job stands alone and answers with the finished clip (within 580 seconds). In a job, send pictures and sounds inline (data: URI or plain base64) and voices by their ready id. For full quality send "quality": "hq": one call makes the draft pass and its upscale.

Quality

draft (default)hq
WhatOne fast pass at half size (352 × 608 for 9:16)The same pass, upscaled with a detail pass to full size (704 × 1216)
ForChecking motion, framing, timing, speech and soundThe video you deliver
LooksSoft; faces and eyes are smeared at this sizeSharp faces and eyes

The same seed and request give the same motion, so a draft you like can be made again as hq with its seed.

/v1/jobs/talking-video fields

FieldDefaultDescription
photorequiredThe person who talks; the video opens on it
wordsrequired (or audio)What they say: up to about 13 s of speech (some 30 words). The clip's length follows the words (5–15 s)
voicechosen by the modelA ready voice id, for example emma, anna or mike
languageenThe language of words: en es fr de it pt ru ja ko zh he ar nl pl tr (or the English name)
audiononeInstead of words and voice: a finished recording; the lips follow it
seconds, format, quality, detail_steps, seed, crop, upload_urlAs below

The answer also has prompt: the prompt the program wrote for you. Send an edited version to /v1/jobs/image-to-video for full control.

/v1/jobs/text-to-video and /v1/jobs/image-to-video fields

FieldDefaultDescription
promptrequiredThe H3 prompt, sent to the model as is (see "Writing the prompt")
seconds5 (with audio: its length)Whole seconds, 1–15. With audio, at least the audio's length
formatthe frame's shape, else 9:169:16, 16:9, 1:1, 3:4, 4:3, 2:3, 3:2, 21:9
qualitydraftdraft or hq
detail_steps1hq detail-pass steps, 1–3
seedrandomThe same seed and request give the same motion
first_framenoneThe video opens on exactly this picture (cut to format at crop). It is also <Picture 1>, the look reference, unless first_frame_is_reference: false
crop{"x": 0.5, "y": 0.3}Where the frame sits on a picture of another shape
last_framenoneThe video ends on this picture
audiononeFinished speech or sound, up to 15 s. The clip's soundtrack is this recording and the picture lip-syncs to it. Write the speaking in plain words ("she talks to the camera")
voicenoneA ready voice id: <Audio 1>, the voice for speech your prompt writes in <d> lines
referencesnone{"images": [up to 9], "audios": [up to 3]}. Images are <Picture 2>… after a first frame (else from <Picture 1>). Audios are voice samples (about 10 s of one clean voice)
upload_urlnoneYour own presigned PUT URL; the finished MP4 is also uploaded there

Response (200)

JSON
{"video": "<base64 MP4>", "mime_type": "video/mp4", "seed": 8121, "quality": "draft", "format": "9:16", "seconds": 5, "render_seconds": 18.4}

Plus upload when you sent upload_url, and prompt on talking-video. Any error is a non-2xx answer {"error": "..."}.

Writing the prompt

An H3 prompt has six sections: subject_definitions, summary, retention_analysis, detailed_description, overall_soundscape, non_diegetic_music. Refer to inputs with exactly the labels you sent: <Picture n>, <Audio n>, and one <Subject n> per person. Name the task type in the summary: first or last frame = [keyframe completion], references = reference generation, a voice sample = audio reference; combine them with + . Speech written by the model goes in <d> lines at its moment, for example At 00:01.600, she says: <d>[English] Welcome back.</d>.

MiniMax's own prompt guide is served by the program on your machine: GET <capability_url>/v1/prompt-guide.

On your own machine

Beyond the job routes, a machine of your own offers: a clip queue (POST /v1/text-to-video, /v1/image-to-video, /v1/talking-video answer 201 with a clip id; GET /v1/clips/{id}?wait=N); POST /v1/clips/{id}/hq (the full-quality take of a finished draft, same seed, prompt and motion); POST /v1/clips/{id}/cancel; GET /v1/clips; chains of clips (continue_from, end_on) and POST /v1/join to join clips into one video; GET /v1/voices and POST /v1/voices (save your own voice sample, 3–30 s, under a name; it is gone at the next start); uploads (POST /v1/uploads/photo, /v1/uploads/voice); GET /v1/status. Full details: GET <capability_url>/v1.


Sending a video to your own bucket

Both video programs accept upload_url: a presigned PUT URL for the object you want, in Amazon S3, Cloudflare R2 or any S3-compatible store, valid for at least the render time plus a few minutes. When the clip is made, the machine uploads the MP4 there (Content-Type: video/mp4); sign the URL either without a content type or with video/mp4. Your bucket keys never reach GPU Forge, only the one URL.

Python
import boto3
url = boto3.client("s3").generate_presigned_url(
    "put_object",
    Params={"Bucket": "my-videos", "Key": "clips/coast.mp4", "ContentType": "video/mp4"},
    ExpiresIn=3600,
)
# then send {"prompt": "...", "upload_url": url}

This page as Markdown, for tools and agents: /docs/programs.md