FLUX.2 is the image generation and editing family Black Forest Labs ships today, with its own API: requests go to api.bfl.ai, the reference lives on docs.bfl.ai, and keys come from dashboard.bfl.ai. This article runs that path end to end, then states what the official pages publish and what they leave out.

Black Forest Labs has since announced FLUX 3, a multimodal line. FLUX.2 remains the image family covered here, and the FLUX hub carries the tier table.

What the FLUX.2 API exposes

The hosted API serves [max], [pro], [flex] and [klein]. The pricing documentation lists [dev] as “Local only — Open weights, non-commercial (no hosted API)”, and the model overview notes that the Base variants “are not offered on the public API”.

A job is one POST that returns work to poll, not a picture. You send the prompt and the output size with an x-key header, the response carries an id and a polling_url, you poll until status reads Ready, and the image arrives as result.sample, a signed URL valid for ten minutes.

Two constraints belong in your code: width and height must be multiples of 16, between 64×64 and 4 MP. FLUX.2 also does not support negative prompts.

Getting a key from the BFL dashboard

dashboard.bfl.ai is the whole access path: register with an email address, verify it, buy credits at “1 credit = $0.01 USD”, and create a key.

The quick-start page warns that the key is shown once, at creation. Keep it in a secret manager, never in front-end code, because a key a browser can read is a public key.

A second official route needs no key. Black Forest Labs runs an MCP server at https://mcp.bfl.ai, documented as claude mcp add --transport http FLUX https://mcp.bfl.ai over OAuth. That suits assistants; a backend pipeline still wants the key. To meet the model in a browser first, how to use FLUX covers the playground.

Your first request: REST against api.bfl.ai

Preview endpoints and pinned snapshots

The overview lists flux-2-pro-preview, the latest FLUX.2 [pro] model, beside flux-2-pro, a fixed snapshot for reproducibility, with flux-2-klein-9b-preview and flux-2-klein-9b following the same pattern. One official sentence settles the choice: preview and non-preview endpoints share the same API contract, so switching between them is a string change.

Official FLUX.2 example of a glass jar filled with branded capsules whose logo is reproduced exactly
Black Forest Labs
# Requires curl and jq. The key comes from dashboard.bfl.ai.
API_BASE="https://api.bfl.ai/v1"
MODEL="flux-2-pro-preview"

# 1. Submit the job and keep the polling URL the response hands back.
curl -s -X POST "${API_BASE}/${MODEL}" \
  -H "x-key: ${BFL_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A ceramic espresso cup on a walnut counter, oblique morning light, shallow depth of field.",
    "width": 1024,
    "height": 1024
  }' > submit.json

polling_url=$(jq -r .polling_url submit.json)

# 2. Poll until the status reads Ready.
while true; do
  curl -s -H "x-key: ${BFL_API_KEY}" "${polling_url}" > poll.json
  [ "$(jq -r .status poll.json)" = "Ready" ] && break
  sleep 1
done

# 3. Download in the same run: the signed URL lives for ten minutes.
curl -sL -o flux-2-output.png "$(jq -r .result.sample poll.json)"

Authentication is one x-key header, not a bearer token. The submit call returns a polling URL instead of an image, which is the only reason the loop exists. And width and height are a documented requirement, so pick sizes that divide by 16.

Multi-reference editing in the request body

How the nine-megapixel budget works

Editing keeps the same endpoint and adds fields: input_image, input_image_2, onward, one reference each. The model overview caps them per tier — [klein] up to 4, [max], [pro] and [flex] up to 8 through the API and 10 in the playground, [dev] a recommended maximum of 6.

The resolution arithmetic comes from the prompting guide. On the API, [pro] has a 9 MP limit covering input plus output: 1 MP of output allows up to 8 reference images, 2 MP up to 7, and the count falls as output grows. Billing is separate: each reference is charged as 1 MP whatever output size you asked for, and any reference above 1 MP is downscaled to 1 MP when several are sent.

[klein] ships without prompt upsampling, so descriptive prompts matter more there. A reseller may cap lower: the kie.ai API reference documents a maximum of 8 input images, which is that channel’s own figure.

Saving the returned image to a file

The signed URL is why the download has to happen inside the same run: poll, take result.sample, fetch it, write the bytes, finish inside ten minutes.

// Node 18+ for global fetch. Reads BFL_API_KEY from the environment.
import { writeFile } from 'node:fs/promises';

const API_BASE = 'https://api.bfl.ai/v1';
const MODEL = 'flux-2-pro-preview';

const submit = await fetch(`${API_BASE}/${MODEL}`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-key': process.env.BFL_API_KEY,
  },
  body: JSON.stringify({
    prompt:
      'A ceramic espresso cup on a walnut counter, oblique morning light.',
    width: 1024,
    height: 1024,
  }),
});
if (!submit.ok) throw new Error(`submit failed: ${submit.status}`);

const { polling_url: pollingUrl } = await submit.json();

let result;
for (let attempt = 0; attempt < 60; attempt += 1) {
  const poll = await fetch(pollingUrl, {
    headers: { 'x-key': process.env.BFL_API_KEY },
  });
  const body = await poll.json();
  if (body.status === 'Ready') {
    result = body.result;
    break;
  }
  await new Promise((resolve) => setTimeout(resolve, 1000));
}
if (!result) throw new Error('no result after 60 polls');

const image = await fetch(result.sample);
await writeFile('flux-2-output.png', Buffer.from(await image.arrayBuffer()));
console.log('wrote flux-2-output.png');

The script reuses the values the submit response returned, waits by polling rather than resubmitting, and stops after 60 attempts so a stuck job cannot hold a worker.

What the official pages publish, and what they do not

The pricing documentation quotes everything in megapixels: 1 credit = $0.01 USD, per image, the same rate for the API and the playground.

TierWhat the official pricing pages state
FLUX.2 [max]from $0.07 per megapixel
FLUX.2 [pro]from $0.03 per megapixel for generation, from $0.045 per megapixel for editing
FLUX.2 [flex]$0.05 per megapixel on the pricing page; the model overview states $0.06 per megapixel
FLUX.2 [klein]from $0.014 per image for 4B, from $0.015 per image for 9B
FLUX.2 [dev]no hosted API: “Local only — Open weights, non-commercial”

The first megapixel is charged flat and each additional one is added to the total. The documented example: a 2 MP image on klein 4B costs $0.014 plus $0.001. Batch requests multiply the base cost by the image count, fine-tuned endpoints bill at their base endpoint’s rate during the public beta, and output is capped at 4 MP for every operation.

Several things stay unpublished. There is no free API allowance — the free demo advertised is the playground, which needs no signup and no card, not a monthly grant of API images. No success rate, benchmark score or head-to-head comparison appears on any official page, regional availability and compliance status are not broken down by country, and the commercial licence tiers for the open-weight builds are named with their allowances but no unit price.

Where official figures disagree, the disagreement is between official pages: [flex] appears at $0.05 per megapixel in the pricing table and $0.06 in the overview, so cite the page you read. Open weights are a separate track from the hosted API: the release notes describe [klein] 4B under Apache 2.0 and [klein] 9B under the FLUX Non-Commercial License, while the pricing table lists [dev] as local only. For another hosted image family, the Nano Banana hub and the GPT Image hub cover the same access questions.

Frequently asked questions

Is there a free tier for the FLUX.2 API? No free API allowance is published. The free demo advertised is the playground, with no signup and no card; API calls are billed in credits.

Which endpoint should I call? flux-2-pro-preview for the current [pro] build, flux-2-pro for a reproducible snapshot, a klein endpoint when cost or latency decides. The contract is identical.

How many reference images fit in one request? Up to 4 on [klein], up to 8 through the API on [max], [pro] and [flex], 10 in the playground, a recommended maximum of 6 on [dev]. The 9 MP input-plus-output limit on [pro] lowers that as output rises.

Does FLUX.2 take negative prompts? No. Fold the exclusions into positive description instead.

Do I have to poll for a result? Yes. Submit returns a job with a polling_url, and the image appears as result.sample only once the status reads Ready.

Keep the key in a secret manager, keep the model id in configuration, and download inside the polling run.