Async & Polling

All Fluxpool generations are asynchronous — the initial POST returns immediately with a generation id and a presigned S3 URL. This page covers how to check when your generation is ready.

🚧

Webhooks are coming soon

Webhook delivery is on the roadmap. Until then, please poll — either the shared generation-status endpoint, or the presigned S3 URL that the initial response hands you.

If you were expecting a webhook_url parameter on the generation endpoints: the ingestion Lambda currently accepts the field but does not deliver callbacks. Don't rely on it.

Two polling patterns

The initial POST response looks like this:

json — initial response
{
  "created": 1785845810,
  "id": "6dcc89ce-964e-466e-8100-ba2bdfb6d07c",
  "status": "pending",
  "model": "flux-2-pro",
  "type": "image",
  "data": [
    {
      "url": "https://fluxpool-output.s3.ap-southeast-1.amazonaws.com/...?X-Amz-...",
      "generation_id": "6dcc89ce-964e-466e-8100-ba2bdfb6d07c",
      "status": "pending",
      "model": "flux-2-pro",
      "revised_prompt": null
    }
  ]
}

You have two ways to know when it's done:

Option 1 — Poll the generation-status endpoint

Best for structured status information (progress, errors, model name).

bash
curl https://api.fluxpool.ai/v1/generations/6dcc89ce-964e-466e-8100-ba2bdfb6d07c \
  -H "Authorization: Bearer fp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Poll every 3 seconds until status is "completed". Possible values: pending, processing, completed, failed.

Option 2 — Poll the presigned S3 URL directly

Cheaper — bypasses the Fluxpool API entirely. Best for image workloads where you just want the bytes.

bash
curl -I --range 0-0 "https://fluxpool-output.s3.ap-southeast-1.amazonaws.com/...?X-Amz-..."

Important: S3 presigned GET URLs reject HEAD requests with a 403. Use GET with Range: bytes=0-0 for a cheap readiness probe — you'll get a 200 and one byte when the file is available.

Presigned URL expiry

Every presigned URL is valid for 1 hour from the moment the generation was submitted (controlled by the PRESIGNED_URL_EXPIRY environment setting, currently 3600 seconds).

Persist the file to your own storage promptly once it's ready — after the URL expires you'll need a fresh one from GET /v1/generations/{id}.

Complete Python example

python
import time
import requests

API_KEY = "fp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
headers = {"Authorization": f"Bearer {API_KEY}"}

# 1. Submit
submit = requests.post(
    "https://api.fluxpool.ai/v1/videos/generations",
    headers=headers,
    json={
        "model": "seedance-v2",
        "prompt": "A drone shot over a coral reef",
        "duration": 5,
        "resolution": "720p",
    },
).json()

gen_id = submit["id"]

# 2. Poll status
while True:
    status = requests.get(
        f"https://api.fluxpool.ai/v1/generations/{gen_id}",
        headers=headers,
    ).json()

    if status["status"] == "completed":
        video_url = status["data"][0]["url"]
        break
    if status["status"] == "failed":
        raise RuntimeError(status.get("error", "generation failed"))

    time.sleep(3)

# 3. Persist to your own storage before the URL expires (1 hour).
open("video.mp4", "wb").write(requests.get(video_url).content)