FLUX 3 Klein Image Edit API

Black Forest Labsimage$0.011 / image

Submit a FLUX 3 Klein Image Edit run over HTTP, then poll it or take a webhook. Results are files on media.ezflows.io. Try it in the playground first.

Async: the POST answers at once with a request id. Poll it, or take the webhook.

  1. 01

    Submit

    Parameters at the top level of the JSON body. Answers 202 with a request id.

    curlPOST /v1/models/flux-3-klein-image-edit
    curl -X POST https://api.ezflows.io/v1/models/flux-3-klein-image-edit \
      -H "Authorization: Bearer $EZFLOWS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "images": [
          "https://media.ezflows.io/inputs/<account>/<upload-id>.png"
        ],
        "prompt": "Recolour only the motorcycle'\''s fuel tank from cherry red to brushed copper. Keep the chrome, the tyres, the pegboard of hand tools, the brick wall and the lighting exactly unchanged.",
        "resolution": "1k",
        "aspect_ratio": "auto",
        "output_format": "jpeg"
      }'
    
    # 202 Accepted, at once — it never waits for the model:
    # {"request_id": "req_8f2a41c9b70e4d15", "status": "queued",
    #  "poll_url": "https://api.ezflows.io/v1/requests/req_8f2a41c9b70e4d15"}
  2. 02

    Poll

    Same bearer header, every few seconds, until the status is final.

    curlGET /v1/requests/:id
    REQUEST_ID=req_8f2a41c9b70e4d15   # from the POST
    
    while :; do
      BODY=$(curl -s https://api.ezflows.io/v1/requests/$REQUEST_ID \
        -H "Authorization: Bearer $EZFLOWS_API_KEY")
      STATUS=$(echo "$BODY" | jq -r .data.status)
      case "$STATUS" in succeeded|failed|cancelled) break ;; esac
      sleep 3
    done
    
    echo "$BODY" | jq -r '.data.output.artifacts[].url'   # media.ezflows.io, kept 90 days
  3. 03

    Response

    Files are on media.ezflows.io, kept 90 days. A failed run says why and costs nothing.

    json200 · succeeded
    {
      "data": {
        "id": "req_8f2a41c9b70e4d15",
        "model_slug": "flux-3-klein-image-edit",
        "status": "succeeded",
        "http_status": 200,
        "cost": 0.01144,
        "auth_method": "api_key",
        "error": null,
        "submitted_at": "2026-09-12T18:07:21.114Z",
        "queue_started_at": "2026-09-12T18:07:21.402Z",
        "execution_started_at": "2026-09-12T18:07:22.010Z",
        "first_byte_at": "2026-09-12T18:07:52.871Z",
        "finished_at": "2026-09-12T18:07:55.203Z",
        "io_deleted_at": null,
        "canvas_id": null,
        "canvas_node_id": null,
        "client_attempt_id": null,
        "idempotency_key": null,
        "input": {
          "images": [
            "https://media.ezflows.io/inputs/<account>/<upload-id>.png"
          ],
          "prompt": "Recolour only the motorcycle's fuel tank from cherry red to brushed copper. Keep the chrome, the tyres, the pegboard of hand tools, the brick wall and the lighting exactly unchanged.",
          "resolution": "1k",
          "aspect_ratio": "auto",
          "output_format": "jpeg"
        },
        "output": {
          "artifacts": [
            {
              "index": 0,
              "kind": "image",
              "contentType": "image/jpeg",
              "url": "https://media.ezflows.io/outputs/<account>/req_8f2a41c9b70e4d15/0.jpg"
            }
          ]
        }
      }
    }
  4. 04

    Webhook

    Skip polling: we POST the result to your endpoint, at least once.

    Register
    Create an endpoint under Webhooks in the dashboard; the signing secret is shown once.
    Events
    request.succeeded · request.failed · request.cancelled
    Headers
    ezflows-event-id (dedupe on it) · ezflows-timestamp (unix seconds) · ezflows-signature t=<ts>,v1=<hex HMAC-SHA256 of "<ts>.<raw body>">
    Verify
    Over the exact bytes received, in constant time; reject anything older than five minutes.
    Respond
    Any 2xx within 10 s. Redirects are not followed.
    Retries
    Five, with backoff: 30 s · 60 s · 2 min · 4 min · 8 min. Disabled after five consecutive dead deliveries.
    jsonDelivery body
    {
      "id": "82cf46a4-841e-41d6-b3c7-facc937d3252",
      "type": "request.succeeded",
      "created_at": "2026-09-12T18:07:55Z",
      "data": {
        "id": "req_8f2a41c9b70e4d15",
        "model_slug": "flux-3-klein-image-edit",
        "status": "succeeded",
        "cost": 0.01144,
        "output": {
          "artifacts": [
            {
              "url": "https://media.ezflows.io/…/0.jpg"
            }
          ]
        }
      }
    }
    curlverify.sh
    # Create the endpoint under Webhooks in the dashboard; the signing secret is shown once.
    # ezflows-signature: t=<ts>,v1=<hex HMAC-SHA256 of "<ts>.<raw body>">
    # body.json = the exact bytes received. Reject anything older than five minutes.
    EXPECTED=$({ printf '%s.' "$TS"; cat body.json; } \
      | openssl dgst -sha256 -hmac "$EZFLOWS_WEBHOOK_SECRET" -r | cut -d' ' -f1)
    
    [ "$EXPECTED" = "$V1" ] && echo "valid" || echo "reject"

Parameters 8

NameTypeDefaultAllowedDescription
imagesrequiredstring[]—up to 10 image urls1 to 10 images to edit, restyle or combine. The first is the image being edited. Refer to them in the prompt as Image 1, Image 2 or <ref_image_1>, <ref_image_2>. URL or base64.
promptrequiredstringRecolour only the motorcycle's fuel tank from cherry red to brushed copper. Keep the chrome, the tyres, the pegboard of hand tools, the brick wall and the lighting exactly unchanged.—What to change and what must stay the same. Supports bounding boxes: tag elements with <id> and append a JSON array of {id, bbox:[top,left,bottom,right] on a 0-1000 grid, desc}.
resolutionenum1k768sq · 1k · 1.5k · 2k · 4kOutput size tier (equal pixel area; exact dimensions follow the aspect ratio). Price scales with the tier.
aspect_ratioenumautoauto · 21:9 · 2:1 · 16:9 · 3:2 · 7:5 · 4:3 · 5:4 · 1:1 · 4:5 · 3:4 · 5:7 · 2:3 · 9:16 · 1:2 · 9:21auto keeps the first reference image's aspect ratio.
output_formatenumjpegjpeg · pngjpeg (smaller) or png (lossless).
seedinteger—0–4294967295Fix the seed to reproduce a result; leave empty for a random one.
stepsinteger161–16Denoising steps of the distilled model. 16 is full quality; fewer is faster and rougher. Same price either way.
safety_toleranceinteger20–4Input and output moderation level: 0 is strictest, 4 most permissive.

File inputs (images: up to 10 image urls) take URLs. Upload the raw file to POST /v1/uploads with its own Content-Type and pass the url it returns. Inputs are kept 90 days.