BFL API

The layer under the components: a client that reaches BFL through your server, typed requests for every endpoint, and tasks tracked until they land.

Installation

Components that talk to the API bring it along. To build your own:

pnpm dlx shadcn@latest add https://mgp.paukraft.com/r/bfl.json

Your server

Your API key stays on your server. createBflClient("/api/bfl") posts each request to it and polls through it, so you need two routes:

POST /api/bfl/*endpoint → POST https://api.bfl.ai/v1/{endpoint}
                          with your x-key header and the body
GET  /api/bfl/poll?url=  → GET the task's polling_url, after
                          checking it's on bfl.ai; once Ready,
                          save result.sample to your storage
                          and return your URL in its place

Don't show or stream BFL's result URLs, proxied or not: they expire after about 10 minutes, and they're served without CORS, so the browser can't read their pixels, which marking up a result needs. In the poll route, once a task is Ready, save the result to your storage and return your URL. Some endpoints have a slash, like flux-tools/erase-v1, so match the rest of the path. Or pass your own { submit, poll }, e.g. through server functions.

Requests

One builder per endpoint family, each returning { endpoint, body } with the API's field names. Build the same request on your server to price it, and the cost shown is the cost charged. Fields a builder leaves out, like webhook_url, go on the body.

PropTypeDefault
flux3Image{ prompt, images?, aspectRatio?, resolution?, grounding? }

Generate or edit with FLUX 3: up to 10 images to edit or draw from, a resolution tier from 768sq to 4k.

—
flux2(model, { prompt, images?, width?, height?, seed? })

FLUX.2 max, pro, flex or klein: up to 8 images, sized in pixels.

—
kontext(model, { prompt, images?, aspectRatio?, seed? })

FLUX.1 Kontext pro or max: the first image is the one edited.

—
erase / fill{ image, mask, … }

Remove, or regenerate with a prompt, where the mask is white. Markup makes the mask.

—
outpaint / expand{ image, width, height, x?, y?, prompt? } / { image, top?, … }

Grow the canvas around an image. Outpaint Frame's value is outpaint's input.

—
deblur / tryOn{ image } / { person, garment, prompt? }

Sharpen an image; dress a person in a garment.

—
flux3Video{ prompt, keyframes?, startVideo?, aspectRatio?, duration?, resolution?, audio?, draft? }

A clip with FLUX 3. The mode follows the input: startVideo continues a clip, keyframes set frames, a prompt alone is text to video.

—
flux3VideoEnhance{ draftCache, resolution? }

Renders a draft in full: the same clip, at full quality.

—
videoEdit / videoUpscale{ video, prompt } / { video, prompt?, creative?, factor? }

Edit a clip by instruction; upscale it 1.5 to 3 times.

—

Tasks

PropTypeDefault
useBflTasks(client, { onSubmit? }) => { run, cancel }

Runs tasks by your own ids, e.g. a version or a clip: run(id, request, onResult) reports each result until it settles, and running an id again replaces it, as a retry does. onSubmit sees every request as it's sent, retries included, to charge for it. Runs stop on unmount.

—
GenResult{ status, progress?, src?, error?, draftCache? }

A result as the loaders take it: spread it onto ImageGenLoader, VideoGenLoader or Gen Progress.

—
trackBflTask(submit, { poll, signal, onResult, interval? }) => Promise<void>

One task, by hand: submits, polls and reports until it settles or signal aborts.

—
fromBflResult(result: BflResult) => GenResult

A polling_url response as a GenResult, moderation reasons included.

—

Media

Images on their way to and from the API.

pnpm dlx shadcn@latest add https://mgp.paukraft.com/r/media.json
PropTypeDefault
toMedia(source: string | Blob) => Promise<string>

An image or video as the API takes it: URLs as they are, files and object URLs read into data URLs.

—
compositeMasked(original, result, mask, { feather? }) => Promise<string>

The result laid over the original only where the mask is white: an edit that keeps every other pixel.

—
useImageSize(src?) => { width, height } | undefined

An image's natural size, once it loads.

—
useObjectUrls() => { create, release }

Object URLs for picked files, revoked on release or unmount.

—