Try FLUX.1-Kontext [dev] in the Workbench
Run this model interactively, tune parameters, and compare outputs.
flux-kontext-dev
black-forest-labs/FLUX.1-Kontext-dev is a 12 billion parameter multimodal LVM (vision model) designed for high-fidelity image editing and generation using both text and image inputs.
It excels in iterative image editing, maintaining character, style, and object consistency over multiple successive edits with minimal visual drift. The model reliably performs both local and global modifications, and is noted for its robust contextual understanding and ability to process instructions for precise regional edits or full scene transformations.
Some other noteworthy features of black-forest-labs/FLUX.1-Kontext-dev include:
- Preserving unique elements (like characters or objects) across different scenes and environments, even after several edits.
- Generating novel images with style or character references guided by either text or example images.
| Metric | Value |
|---|---|
| Parameter Count | 12 billion |
| Mixture of Experts | No |
| Context Length | 0K (not applicable for vision model) |
| Multilingual | No |
| Quantized* | Yes |
| Precision* | FP8 |
Example request
Use the Workbench as a request builder: configure parameters for this model in the UI, then open the API tab to copy the exact cURL or Python call.
- Sync
- Async
- Async with SSE
See the image editing reference for more details.
- Minimal
- All parameters
curl -X POST https://hub.oxen.ai/api/ai/images/edit \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OXEN_API_KEY" \
-d '{
"model": "flux-kontext-dev",
"input_image": "https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png",
"prompt": "<prompt>"
}'
import os
import requests
response = requests.post(
"https://hub.oxen.ai/api/ai/images/edit",
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['OXEN_API_KEY']}",
},
json={
"model": "flux-kontext-dev",
"input_image": "https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png",
"prompt": "<prompt>"
},
)
response.raise_for_status()
print(response.json())
curl -X POST https://hub.oxen.ai/api/ai/images/edit \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OXEN_API_KEY" \
-d '{
"model": "flux-kontext-dev",
"input_image": "https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png",
"prompt": "<prompt>",
"aspect_ratio": "16:9",
"num_inference_steps": 28,
"guidance": 2.5,
"output_format": "webp",
"output_quality": 80,
"disable_safety_checker": false
}'
import os
import requests
response = requests.post(
"https://hub.oxen.ai/api/ai/images/edit",
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['OXEN_API_KEY']}",
},
json={
"model": "flux-kontext-dev",
"input_image": "https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png",
"prompt": "<prompt>",
"aspect_ratio": "16:9",
"num_inference_steps": 28,
"guidance": 2.5,
"output_format": "webp",
"output_quality": 80,
"disable_safety_checker": false
},
)
response.raise_for_status()
print(response.json())
See the async queue reference for more details.
- Minimal
- All parameters
# Enqueue, capture the generation id.
GEN_ID=$(curl -s -X POST https://hub.oxen.ai/api/ai/queue \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OXEN_API_KEY" \
-d '{
"model": "flux-kontext-dev",
"input_image": "https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png",
"prompt": "<prompt>"
}' | jq -r '.generations[0].generation_id')
# Poll until the generation reaches a terminal status.
while true; do
STATUS=$(curl -s -H "Authorization: Bearer $OXEN_API_KEY" \
"https://hub.oxen.ai/api/ai/queue/$GEN_ID" | jq -r '.status')
echo "Status: $STATUS"
case $STATUS in succeeded|failed|cancelled) break;; esac
sleep 5
done
# Print the result.
curl -s -H "Authorization: Bearer $OXEN_API_KEY" \
"https://hub.oxen.ai/api/ai/queue/$GEN_ID" | jq .
import os
import time
import requests
HEADERS = {
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['OXEN_API_KEY']}",
}
enqueue = requests.post(
"https://hub.oxen.ai/api/ai/queue",
headers=HEADERS,
json={
"model": "flux-kontext-dev",
"input_image": "https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png",
"prompt": "<prompt>"
},
)
enqueue.raise_for_status()
generation_id = enqueue.json()["generations"][0]["generation_id"]
while True:
data = requests.get(
f"https://hub.oxen.ai/api/ai/queue/{generation_id}",
headers=HEADERS,
).json()
if data["status"] in {"succeeded", "failed", "cancelled"}:
break
time.sleep(5)
if data["status"] == "succeeded":
print(f"Result: {data['result_url']}")
else:
print(f"Generation {data['status']}: {data.get('error_message')}")
# Enqueue, capture the generation id.
GEN_ID=$(curl -s -X POST https://hub.oxen.ai/api/ai/queue \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OXEN_API_KEY" \
-d '{
"model": "flux-kontext-dev",
"input_image": "https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png",
"prompt": "<prompt>",
"aspect_ratio": "16:9",
"num_inference_steps": 28,
"guidance": 2.5,
"output_format": "webp",
"output_quality": 80,
"disable_safety_checker": false
}' | jq -r '.generations[0].generation_id')
# Poll until the generation reaches a terminal status.
while true; do
STATUS=$(curl -s -H "Authorization: Bearer $OXEN_API_KEY" \
"https://hub.oxen.ai/api/ai/queue/$GEN_ID" | jq -r '.status')
echo "Status: $STATUS"
case $STATUS in succeeded|failed|cancelled) break;; esac
sleep 5
done
# Print the result.
curl -s -H "Authorization: Bearer $OXEN_API_KEY" \
"https://hub.oxen.ai/api/ai/queue/$GEN_ID" | jq .
import os
import time
import requests
HEADERS = {
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['OXEN_API_KEY']}",
}
enqueue = requests.post(
"https://hub.oxen.ai/api/ai/queue",
headers=HEADERS,
json={
"model": "flux-kontext-dev",
"input_image": "https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png",
"prompt": "<prompt>",
"aspect_ratio": "16:9",
"num_inference_steps": 28,
"guidance": 2.5,
"output_format": "webp",
"output_quality": 80,
"disable_safety_checker": false
},
)
enqueue.raise_for_status()
generation_id = enqueue.json()["generations"][0]["generation_id"]
while True:
data = requests.get(
f"https://hub.oxen.ai/api/ai/queue/{generation_id}",
headers=HEADERS,
).json()
if data["status"] in {"succeeded", "failed", "cancelled"}:
break
time.sleep(5)
if data["status"] == "succeeded":
print(f"Result: {data['result_url']}")
else:
print(f"Generation {data['status']}: {data.get('error_message')}")
See the async queue reference for more details.
- Minimal
- All parameters
# Enqueue, capture the generation id.
GEN_ID=$(curl -s -X POST https://hub.oxen.ai/api/ai/queue \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OXEN_API_KEY" \
-d '{
"model": "flux-kontext-dev",
"input_image": "https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png",
"prompt": "<prompt>"
}' | jq -r '.generations[0].generation_id')
# Stream the SSE channel, grab the data line that follows a
# media_generation_completed event for our id, and pretty-print it.
curl -sN -H "Authorization: Bearer $OXEN_API_KEY" https://hub.oxen.ai/api/events \
| awk -v id="$GEN_ID" '
/^event: media_generation_completed$/ { expect=1; next }
/^data: / && expect {
payload = substr($0, 7)
if (index(payload, "\"generation_id\":\"" id "\"")) { print payload; exit }
expect = 0
}
' | jq .
import json
import os
import requests
API_KEY = os.environ["OXEN_API_KEY"]
AUTH = {"Authorization": f"Bearer {API_KEY}"}
enqueue = requests.post(
"https://hub.oxen.ai/api/ai/queue",
headers={**AUTH, "Content-Type": "application/json"},
json={
"model": "flux-kontext-dev",
"input_image": "https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png",
"prompt": "<prompt>"
},
)
enqueue.raise_for_status()
generation_id = enqueue.json()["generations"][0]["generation_id"]
with requests.get(
"https://hub.oxen.ai/api/events",
headers=AUTH,
stream=True,
) as stream:
event_name = None
for line in stream.iter_lines(decode_unicode=True):
if line.startswith("event: "):
event_name = line.removeprefix("event: ")
elif line.startswith("data: ") and event_name == "media_generation_completed":
payload = json.loads(line.removeprefix("data: "))
if payload.get("generation_id") == generation_id:
print(payload)
break
# Enqueue, capture the generation id.
GEN_ID=$(curl -s -X POST https://hub.oxen.ai/api/ai/queue \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OXEN_API_KEY" \
-d '{
"model": "flux-kontext-dev",
"input_image": "https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png",
"prompt": "<prompt>",
"aspect_ratio": "16:9",
"num_inference_steps": 28,
"guidance": 2.5,
"output_format": "webp",
"output_quality": 80,
"disable_safety_checker": false
}' | jq -r '.generations[0].generation_id')
# Stream the SSE channel, grab the data line that follows a
# media_generation_completed event for our id, and pretty-print it.
curl -sN -H "Authorization: Bearer $OXEN_API_KEY" https://hub.oxen.ai/api/events \
| awk -v id="$GEN_ID" '
/^event: media_generation_completed$/ { expect=1; next }
/^data: / && expect {
payload = substr($0, 7)
if (index(payload, "\"generation_id\":\"" id "\"")) { print payload; exit }
expect = 0
}
' | jq .
import json
import os
import requests
API_KEY = os.environ["OXEN_API_KEY"]
AUTH = {"Authorization": f"Bearer {API_KEY}"}
enqueue = requests.post(
"https://hub.oxen.ai/api/ai/queue",
headers={**AUTH, "Content-Type": "application/json"},
json={
"model": "flux-kontext-dev",
"input_image": "https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png",
"prompt": "<prompt>",
"aspect_ratio": "16:9",
"num_inference_steps": 28,
"guidance": 2.5,
"output_format": "webp",
"output_quality": 80,
"disable_safety_checker": false
},
)
enqueue.raise_for_status()
generation_id = enqueue.json()["generations"][0]["generation_id"]
with requests.get(
"https://hub.oxen.ai/api/events",
headers=AUTH,
stream=True,
) as stream:
event_name = None
for line in stream.iter_lines(decode_unicode=True):
if line.startswith("event: "):
event_name = line.removeprefix("event: ")
elif line.startswith("data: ") and event_name == "media_generation_completed":
payload = json.loads(line.removeprefix("data: "))
if payload.get("generation_id") == generation_id:
print(payload)
break
Fetch model details
The models endpoint returns the full model object, including itsjson_request_schema.
curl -H "Authorization: Bearer $OXEN_API_KEY" https://hub.oxen.ai/api/ai/models/flux-kontext-dev
Request parameters
Required parameters
| Field | Type | Default | Description |
|---|---|---|---|
input_image | string | — | Image to use as reference. Must be jpeg, png, gif, or webp. Format: uri. |
prompt | string | — | Text description of what you want to generate, or the instruction on how to edit the given image. |
Optional parameters
| Field | Type | Default | Description |
|---|---|---|---|
aspect_ratio | string | "16:9" | Aspect ratio of the generated image. Use ‘match_input_image’ to match the aspect ratio of the input image. One of: 1:1, 16:9, 21:9, 3:2, 2:3, 4:5, 5:4, 3:4, 4:3, 9:16, 9:21, match_input_image. |
num_inference_steps | integer | 28 | Number of inference steps Range: 4 – 50. |
guidance | number | 2.5 | Guidance scale for generation Range: 0 – 10. |
seed | integer | — | Random seed for reproducible generation. Leave blank for random. |
output_format | string | "webp" | Output image format One of: webp, jpg, png. |
output_quality | integer | 80 | Quality when saving the output images, from 0 to 100. 100 is best quality, 0 is lowest quality. Not relevant for .png outputs Range: 0 – 100. |
disable_safety_checker | boolean | false | Disable NSFW safety checker |