FLUX.2 bills by the megapixel and settles in credits, and the two official pages carrying the numbers do not lay them out the same way. Authentication is one x-key header. The rest comes down to four rounding rules that the pricing footnotes state and no official page combines into an example.

Every figure below sits next to the page it came from.

What a FLUX.2 request is billed on

The pricing documentation states the conversion plainly: one credit equals $0.01 USD, and the API and the Playground cost the same. For images, FLUX.2 uses megapixel-based pricing, so cost scales with output resolution rather than a flat per-call fee.

Three inputs decide a bill. Output size sets how many megapixels are charged, the tier sets the rate, and every reference image adds its own charge.

The published rate card, page by page

bfl.ai/pricing splits each tier into a first megapixel, each further megapixel, and a per-reference rate. The docs page gives one flatter “from” figure per operation.

Endpoint pathTierFirst MPEach further MPPer reference image
/v1/flux-2-maxFLUX.2 [max]$0.07$0.03$0.03/MP
/v1/flux-2-proFLUX.2 [pro]$0.03$0.015$0.015/MP
/v1/flux-2-flexFLUX.2 [flex]$0.05$0.05$0.05/MP
/v1/flux-2-klein-4bFLUX.2 [klein] 4B$0.014$0.001$0.001/MP
/v1/flux-2-klein-9bFLUX.2 [klein] 9B$0.015$0.002$0.002/MP

Agreement breaks on one tier: the docs page lists [flex] from $0.05, matching the pricing page, while the model overview prints $0.06 per megapixel. Cite the page and the column you read.

FLUX.2 [dev] is absent on purpose: local only, open weights, non-commercial, no hosted API, so there is no endpoint to bill.

The four rounding rules that decide the total

Four footnotes change the number, and they stack.

  • One megapixel is 1024×1024 pixels, so the divisor is 1,048,576, not 1,000,000.
  • Resolution rounds up to the next whole megapixel, separately for each reference image and for the generated output.
  • Maximum output is 4 MP for all operations, and images above 4 MP are resized to 4 MP.
  • With several references, each image above 1 MP is downscaled to 1 MP and every reference is charged as 1 MP whatever output size was requested. A single reference keeps its original resolution up to 4 MP.

The second rule is the expensive one. A 1440×2048 output holds 2,949,120 pixels: 2.81 megapixels, billed as 3.

Official Black Forest Labs example: a snow leopard, a red panda, a panda, a white dog and a penguin arranged on a stack of televisions under one shared light setup
Black Forest Labs

The fourth rule cuts both ways. Four references on [max] cost 4 × $0.03, and one 4 MP reference costs the same $0.12, because a single reference keeps its resolution while a set is normalised to one megapixel each. The cost sheet for both jobs walks it through.

Costing a request before you send it

The estimator applies the four rules in order. It is plain arithmetic, so it runs offline and spends nothing.

# Rates exactly as published on the image tab of bfl.ai/pricing, in USD per megapixel.
RATES = {
    "flux-2-max":      {"first": 0.07,  "next": 0.03,  "ref": 0.03},
    "flux-2-pro":      {"first": 0.03,  "next": 0.015, "ref": 0.015},
    "flux-2-flex":     {"first": 0.05,  "next": 0.05,  "ref": 0.05},
    "flux-2-klein-4b": {"first": 0.014, "next": 0.001, "ref": 0.001},
    "flux-2-klein-9b": {"first": 0.015, "next": 0.002, "ref": 0.002},
}
MP = 1024 * 1024          # the published definition: 1 MP = 1024 x 1024 px
CREDIT = 0.01             # 1 credit = $0.01 USD


def billed_megapixels(width, height):
    """Round up to the next whole megapixel; above 4 MP the output is resized."""
    pixels = min(width * height, 4 * MP)
    return -(-pixels // MP)


def cost(model, width, height, references=0):
    rate = RATES[model]
    output = billed_megapixels(width, height)
    usd = rate["first"] + max(output - 1, 0) * rate["next"]
    usd += references * rate["ref"]        # several references: 1 MP each
    return round(usd, 4), round(usd / CREDIT)


for job in [("flux-2-pro", 1440, 2048, 0), ("flux-2-max", 1024, 1024, 4)]:
    usd, credits = cost(*job)
    print(job, "->", f"${usd:.3f}", f"({credits} credits)")

Run it and you get flux-2-pro 1440x2048 at $0.060 (6 credits) and flux-2-max 1024x1024 with four references at $0.190 (19 credits).

What the estimator does, line by line

billed_megapixels caps at four megapixels and then ceilings, the order the footnotes imply: the cap is a resize, rounding applies afterwards. -(-pixels // MP) is integer ceiling division, so no float rounding can drop a megapixel. The reference charge multiplies straight through. Keep RATES in configuration; rates move.

Running the same job against the live API

Submit is one POST that returns work to poll, and the download has to happen in the same run because the signed URL lives for ten minutes.

# Requires curl and jq. Set BFL_API_KEY first; keys come from dashboard.bfl.ai.
BASE="https://api.bfl.ai/v1"

curl -s -X POST "${BASE}/flux-2-pro-preview" \
  -H "x-key: ${BFL_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"A ceramic espresso cup on a walnut counter, oblique morning light.","width":1440,"height":2048}' \
  > submit.json

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

while true; do
  curl -s -H "x-key: ${BFL_API_KEY}" "${polling_url}" > poll.json
  status=$(jq -r .status poll.json)
  if [ "$status" = "Ready" ]; then break; fi
  if [ "$status" = "Error" ] || [ "$status" = "Failed" ]; then echo "generation failed"; exit 1; fi
  sleep 0.5
done

curl -sL -o flux-2-pro.png "$(jq -r .result.sample poll.json)"

The Python client does the same with explicit failure handling, where a budget problem usually surfaces first.

# pip install requests
import os, time, requests

BASE = "https://api.bfl.ai/v1"
HEADERS = {"x-key": os.environ["BFL_API_KEY"], "Content-Type": "application/json"}

r = requests.post(
    f"{BASE}/flux-2-pro-preview",
    headers=HEADERS,
    json={"prompt": "A ceramic espresso cup on a walnut counter.",
          "width": 1440, "height": 2048},
)
r.raise_for_status()
job = r.json()

deadline = time.time() + 120
while time.time() < deadline:
    time.sleep(0.5)
    poll = requests.get(job["polling_url"], headers=HEADERS).json()
    if poll["status"] == "Ready":
        print(poll["result"]["sample"])   # signed URL, valid for ten minutes
        break
    if poll["status"] in ("Error", "Failed"):
        raise SystemExit(poll)

What 402 and 429 do to a budget

Two status codes belong in the cost conversation. Running out of credits returns 402, and the API allows 24 active tasks with 429 past that; flux-kontext-max is capped at 6. A pool sized above 24 does not fail, it makes the queue expensive in time, and a 402 mid-batch leaves a job set half paid for.

How output size moves the bill

Rounding and the 4 MP cap interact, and pricing a row of common sizes on one tier is the cheapest way to see it.

# What the round-up rule and the 4 MP cap do to one FLUX.2 [pro] job.
# Rate: $0.03 for the first megapixel, $0.015 for each further one.
sizes = [(1024, 1024), (1440, 2048), (1920, 1080), (3840, 2160)]
for w, h in sizes:
    px = min(w * h, 4 * 1024 * 1024)          # output above 4 MP is resized to 4 MP
    mp = -(-px // (1024 * 1024))              # round up to whole megapixels
    usd = 0.03 + max(mp - 1, 0) * 0.015
    print(f"{w}x{h}  {w * h / 1048576:5.2f} raw MP -> {mp} billed MP -> ${usd:.3f}")

The output reads: 1024×1024 bills 1 MP and $0.030, 1440×2048 bills 3 MP and $0.060, 1920×1080 bills 2 MP and $0.045, 3840×2160 bills 4 MP and $0.075. That last line is the cap working: 7.91 megapixels of request is delivered and charged at 4. The habits that keep a job from being re-rolled are in the FLUX.2 prompt guide.

Batch, editing and fine-tuned endpoints

Batch requests multiply the base cost by the number of images. The worked example on the pricing page sends a FLUX.2 [pro] batch of four and goes from $0.03 for a single image to from $0.12. That is multiplication, not a volume discount.

Image editing is where the two pages stop being interchangeable. The docs table lists [pro] image editing from $0.045, while bfl.ai/pricing lists [pro] reference images at $0.015 per megapixel. Different columns, different quantities.

Fine-tuned endpoints bill at their base endpoint’s rate during the public beta. The published example is flux-2-klein-9b-kv-finetuned, charged the same as flux-2-klein-9b at the same resolution. The page adds that this may change once the beta ends.

What the pricing pages leave out

  • No free API allowance, signup credits or trial grant. The quick-start flow goes from registering to buying credits, and auto top-up uses a $5 threshold with a target at least $10 above it, which is a recharge rule rather than a purchase minimum.
  • No per-country pricing, and no price difference between the European and US endpoints.
  • No success rate or benchmark score, so cost per accepted image cannot be derived from anything the vendor publishes.
  • No unit price for the commercial open-weights tiers. The licensing page names Builder, Platform, Professional and Enterprise, and routes every card to Contact Sales.

Frequently asked questions

Is there a free tier for the FLUX.2 API? No free API allowance is published. The free entry point is the open-weight build, which is a licence rather than a quota.

Does a bigger output always cost more? No. Above 4 MP the output is resized to 4 MP, so a 4 MP job and an 8 MP job are billed alike. Below that, rounding up to whole megapixels decides.

How do references change the price? On multi-reference jobs each reference is charged as 1 MP whatever the output size, so four references on [max] add $0.12. A single reference up to 4 MP keeps its resolution and is charged at it.

Why two prices for [pro] editing? The official pages use different columns: $0.045 in the docs table, a $0.015 per-megapixel reference rate on the pricing page. Cite both with their page.

Keep the rate table in configuration, run the estimator before a batch, and read 402 and 429 as cost signals. The request mechanics are in the FLUX.2 API guide, and the browser walkthrough covers the surface where the same rate applies.