---
name: bfl
description: Use when building applications that generate, edit, or manipulate
  images and video using FLUX models. Reach for this skill when integrating
  image/video generation APIs, managing asynchronous generation workflows,
  handling rate limits and polling, or implementing production-grade media
  generation pipelines.
metadata:
  mintlify-proj: bfl
  version: "1.0"
---

# BFL (Black Forest Labs) FLUX API

## Product Summary

BFL provides REST APIs for generating and editing images and video using FLUX models. FLUX 3 is the latest multimodal model supporting text-to-video, image-to-video, video continuation, and image generation/editing with synchronized audio. FLUX.2 offers multiple variants (klein, pro, flex, max) for different speed/quality tradeoffs. All generation is asynchronous: submit a request, receive a `polling_url`, poll until `Ready`, then download the result.

**Key files and endpoints:**
- Primary endpoint: `https://api.bfl.ai/v1/` (use returned `polling_url` for polling)
- Regional endpoints: `api.eu.bfl.ai`, `api.us.bfl.ai` (GDPR-compliant, US-only routing)
- API key format: `bfl_<random-string>` (scoped to projects, shown once at creation)
- Authentication: `x-key` header with API key
- Pricing: 1 credit = $0.01 USD; video priced per second by resolution; images by megapixels

**Primary docs:** https://docs.bfl.ai

## When to Use

Reach for this skill when:
- Building image or video generation features into applications
- Integrating FLUX models (FLUX 3, FLUX.2 variants) into production systems
- Implementing asynchronous generation workflows with polling or webhooks
- Handling rate limits (24 concurrent requests max for most endpoints, 6 for kontext-max)
- Managing API keys, organizations, and projects for team access
- Downloading and re-serving generated media (10-minute expiration on delivery URLs)
- Fine-tuning models with LoRA training or using pre-trained LoRAs
- Connecting FLUX to Claude or other MCP-compatible clients
- Troubleshooting moderation flags, content filtering, or generation failures

## Quick Reference

### API Request Pattern

All generation follows the same async pattern:

```bash
# 1. Submit request
curl -X POST https://api.bfl.ai/v1/flux-3-image \
  -H "x-key: $BFL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "...", "aspect_ratio": "16:9"}'

# Returns: {"id": "...", "polling_url": "...", ...}

# 2. Poll the returned polling_url
curl "$POLLING_URL" -H "x-key: $BFL_API_KEY"

# Returns: {"status": "Pending|Ready|Error|Request Moderated|Content Moderated", ...}

# 3. When status is Ready, download from result.sample
# URLs expire: images after 1 hour, videos after 2 hours, delivery URLs after 10 minutes
```

### Model Selection

| Model | Best For | Speed | Quality | Multi-ref | Pricing |
|-------|----------|-------|---------|-----------|---------|
| FLUX 3 Image | General image gen/edit | Medium | Highest | Up to 10 | $0.055/MP first, $0.011/MP additional |
| FLUX 3 Video | Video gen with audio | Slow (minutes) | Highest | N/A | $0.10–0.80/s depending on resolution |
| FLUX.2 [max] | Highest quality, grounding search | Medium | Highest | Up to 8 | $0.055/MP first |
| FLUX.2 [pro] | Production-grade, balanced | Medium | High | Up to 8 | $0.025/MP first |
| FLUX.2 [flex] | Typography, fine control | Medium | High | Up to 8 | $0.025/MP first |
| FLUX.2 [klein] 9B | Sub-second, quality | Sub-second | Good | Up to 4 | $0.015/MP first |
| FLUX.2 [klein] 4B | Sub-second, high volume | Sub-second | Good | Up to 4 | $0.010/MP first |

### Common Endpoints

| Endpoint | Purpose | Mode |
|----------|---------|------|
| `/v1/flux-3-image` | Generate/edit images | POST |
| `/v1/flux-3-video` | Generate/edit video with audio | POST (modes: t2v, i2v, v2v, draft_enhance) |
| `/v1/flux-2-pro` | FLUX.2 [pro] text-to-image/edit | POST |
| `/v1/flux-2-max` | FLUX.2 [max] with grounding search | POST |
| `/v1/flux-2-klein-9b` | FLUX.2 [klein] 9B fast inference | POST |
| `/v1/flux-tools/video-edit-v1` | Edit existing video clip | POST |
| `/v1/get-result` | Poll result by request ID | GET |

### Status Codes and Responses

| HTTP Status | Meaning | Action |
|-------------|---------|--------|
| 200 | Success | Parse response |
| 400 | Bad request | Check request format and required fields |
| 402 | Insufficient credits | Add credits to organization |
| 429 | Rate limit (too many concurrent) | Wait for slot, use exponential backoff |
| 422 | Invalid parameters | Validate field types and constraints |
| 500/503 | Server error | Retry with backoff |

| Poll Status | Meaning | Action |
|-------------|---------|--------|
| Pending | Still processing | Keep polling |
| Ready | Complete, download available | Fetch from result.sample |
| Request Moderated | Input flagged before processing | Adjust prompt/image, resubmit |
| Content Moderated | Output flagged after processing | Adjust prompt, resubmit |
| Error | Generation failed | Check error details, retry or adjust |

### Environment Setup

```bash
# Store API key securely
export BFL_API_KEY="bfl_your_key_here"

# Never expose in client-side code or version control
# Treat like a password
```

## Decision Guidance

### When to Use Each FLUX.2 Variant

| Need | Choose | Why |
|------|--------|-----|
| Real-time generation, high volume | [klein] 4B or 9B | Sub-second inference, lowest cost |
| Production quality at scale | [pro] | Balanced quality/speed/cost |
| Maximum quality, final assets | [max] | Highest fidelity, grounding search for real-time info |
| Typography, small details | [flex] | Best text rendering, adjustable guidance |
| Local development, research | [dev] (open weights) | Full control, fine-tuning, no API costs |

### When to Use Video Modes

| Scenario | Mode | Input |
|----------|------|-------|
| Generate from text alone | `t2v` (text-to-video) | prompt only |
| Animate a still or keyframes | `i2v` (image-to-video) | prompt + 1–10 images |
| Continue existing clip | `v2v` (video-continuation) | prompt + existing video |
| Iterate before committing | `draft: true` | Same as above, returns fast preview |
| Finalize draft at full quality | `draft_enhance` | draft_cache from previous draft |

### Polling vs Webhooks

| Approach | Use When | Tradeoff |
|----------|----------|---------|
| Polling | Building simple scripts, testing | Simple but requires active waiting |
| Webhooks | Production systems, background jobs | More complex but scales better |
| MCP (Claude/Cursor) | Interactive creative work | No API key management, OAuth |

## Workflow

### 1. Set Up Account and API Key

1. Create account at dashboard.bfl.ai
2. Verify email
3. Add credits (start with $10–20 to experiment)
4. Navigate to API → Keys in your project
5. Click Add Key, give it a descriptive name
6. Copy immediately (shown only once)
7. Store in environment variable: `export BFL_API_KEY="bfl_..."`

### 2. Submit a Generation Request

1. Choose model and endpoint based on use case
2. Prepare payload with required fields (prompt, images if editing)
3. POST to endpoint with `x-key` header
4. Extract `polling_url` from response
5. Store `id` for reference

### 3. Poll for Result

1. Loop: GET `polling_url` with `x-key` header every 1–2 seconds
2. Check `status` field
3. If `Pending`/`Reasoning`/`Generating`: continue polling
4. If `Ready`: proceed to download
5. If `Error`/`Request Moderated`/`Content Moderated`: handle error (see Common Gotchas)

### 4. Download and Store Result

1. Extract URL from `result.sample`
2. Download immediately (URLs expire: 1 hour for images, 2 hours for video, 10 minutes for delivery URLs)
3. Save to your own storage (S3, CDN, local disk)
4. Serve from your infrastructure, not from delivery URLs
5. Never send `x-key` header to delivery URLs

### 5. Handle Errors and Retries

1. Check HTTP status code
2. If 429 (rate limit): wait exponentially (2^attempt seconds), retry
3. If 402 (insufficient credits): add credits, retry
4. If 400/422 (bad request): fix payload, retry
5. If moderated: adjust prompt/image, resubmit
6. If 500/503: wait and retry with backoff

## Common Gotchas

- **Delivery URLs expire quickly.** Images expire after 1 hour, videos after 2 hours. Download immediately and re-serve from your own infrastructure. Do not store URLs.
- **No CORS on delivery URLs.** Cannot use `result.sample` directly in browser. Download server-side and re-serve.
- **API keys shown once.** Copy immediately when created. If lost, delete and create a new one.
- **Rate limits are concurrent, not per-second.** 24 concurrent requests max (6 for kontext-max). 429 means wait for a slot, not retry in a loop.
- **Polling URL must be used.** When using global or regional endpoints, always use the `polling_url` returned in the response, not a hardcoded endpoint.
- **Moderation can flag input or output.** `Request Moderated` = input rejected before processing. `Content Moderated` = output rejected after processing. Adjust prompt/image and resubmit.
- **Video generation takes minutes.** Not seconds. Use `draft: true` to iterate quickly, then `draft_enhance` to finalize.
- **Prompt upsampling for Klein.** FLUX.2 [klein] does not include prompt upsampling; write detailed, descriptive prompts.
- **Multi-reference limits vary.** FLUX 3 Image: up to 10. FLUX.2 [max]/[pro]/[flex]: up to 8. [klein]: up to 4.
- **Signed URLs are region-specific.** Delivery URLs use `delivery.*.bfl.ai`; region identifiers can change. Whitelist `delivery.*.bfl.ai` in firewalls, not specific hostnames.
- **Webhook verification required.** If using webhooks, verify the signature before processing.
- **Safety tolerance varies by model.** FLUX 3: 0–4. FLUX.2: 0–5. FLUX.1: 0–6. Default is 2. Higher values allow more content.

## Verification Checklist

Before submitting work:

- [ ] API key is stored securely in environment variable, never hardcoded
- [ ] Polling loop uses the `polling_url` returned in the response, not a hardcoded endpoint
- [ ] Error handling covers 429 (rate limit), 402 (credits), 400/422 (bad request), moderation statuses
- [ ] Downloaded images/videos are saved to your own storage, not served from delivery URLs
- [ ] Delivery URLs are downloaded within expiration window (1 hour for images, 2 hours for video)
- [ ] Rate limiting respects 24 concurrent request max (6 for kontext-max)
- [ ] Prompt is detailed and descriptive (especially for [klein] models without upsampling)
- [ ] Multi-reference count does not exceed model limit (10 for FLUX 3, 8 for FLUX.2 [max]/[pro]/[flex], 4 for [klein])
- [ ] Moderation sensitivity (`safety_tolerance`) is set appropriately for use case
- [ ] Video generation uses `draft: true` for iteration, `draft_enhance` for finalization
- [ ] Webhook signatures are verified if using async callbacks
- [ ] Organization has sufficient credits before generating at scale

## Resources

**Comprehensive navigation:** https://docs.bfl.ai/llms.txt

**Critical pages:**
- [Quick Start & API Setup](https://docs.bfl.ai/quick_start/get_started) — Account creation, API keys, first request
- [Integration Guidelines](https://docs.bfl.ai/api_integration/integration_guidelines) — Endpoints, polling, image handling, best practices
- [Error Reference](https://docs.bfl.ai/api_integration/errors) — HTTP status codes, response types, moderation handling

---

> For additional documentation and navigation, see: https://docs.bfl.ml/llms.txt