Try GPT Image 2 Edit in the Workbench
Run this model interactively, tune parameters, and compare outputs.
gpt-image-2-edit
GPT Image 2 Edit is OpenAI’s image editing model available through Fal. It transforms one or more reference images using a text prompt, supporting multi-image composition and accurate preservation of subject identity, text, and layout. Ideal for photo modifications, style transfer, composition changes, and product mockups.
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": "gpt-image-2-edit",
"prompt": "Place the subject on the surface of the moon with Earth rising in the background, photorealistic, cinematic lighting.",
"input_image": [
"https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png"
]
}'
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": "gpt-image-2-edit",
"prompt": "Place the subject on the surface of the moon with Earth rising in the background, photorealistic, cinematic lighting.",
"input_image": [
"https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png"
]
},
)
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": "gpt-image-2-edit",
"prompt": "Place the subject on the surface of the moon with Earth rising in the background, photorealistic, cinematic lighting.",
"input_image": [
"https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png"
],
"resolution": "1024x1024",
"quality": "high",
"num_images": 1,
"output_format": "png"
}'
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": "gpt-image-2-edit",
"prompt": "Place the subject on the surface of the moon with Earth rising in the background, photorealistic, cinematic lighting.",
"input_image": [
"https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png"
],
"resolution": "1024x1024",
"quality": "high",
"num_images": 1,
"output_format": "png"
},
)
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": "gpt-image-2-edit",
"prompt": "Place the subject on the surface of the moon with Earth rising in the background, photorealistic, cinematic lighting.",
"input_image": [
"https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png"
]
}' | jq -r '.generations[0].generation_id')
# Poll the single generation until it 404s (terminal state).
while curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $OXEN_API_KEY" \
"https://hub.oxen.ai/api/ai/queue/$GEN_ID" | grep -q "^200$"; do
sleep 5
done
echo "Done. See the 'Async with SSE' tab to receive the result URL."
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": "gpt-image-2-edit",
"prompt": "Place the subject on the surface of the moon with Earth rising in the background, photorealistic, cinematic lighting.",
"input_image": [
"https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png"
]
},
)
enqueue.raise_for_status()
generation_id = enqueue.json()["generations"][0]["generation_id"]
while True:
resp = requests.get(
f"https://hub.oxen.ai/api/ai/queue/{generation_id}",
headers=HEADERS,
)
if resp.status_code == 404:
break
time.sleep(5)
print("Done. See the 'Async with SSE' tab to receive the result URL.")
# 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": "gpt-image-2-edit",
"prompt": "Place the subject on the surface of the moon with Earth rising in the background, photorealistic, cinematic lighting.",
"input_image": [
"https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png"
],
"resolution": "1024x1024",
"quality": "high",
"num_images": 1,
"output_format": "png"
}' | jq -r '.generations[0].generation_id')
# Poll the single generation until it 404s (terminal state).
while curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $OXEN_API_KEY" \
"https://hub.oxen.ai/api/ai/queue/$GEN_ID" | grep -q "^200$"; do
sleep 5
done
echo "Done. See the 'Async with SSE' tab to receive the result URL."
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": "gpt-image-2-edit",
"prompt": "Place the subject on the surface of the moon with Earth rising in the background, photorealistic, cinematic lighting.",
"input_image": [
"https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png"
],
"resolution": "1024x1024",
"quality": "high",
"num_images": 1,
"output_format": "png"
},
)
enqueue.raise_for_status()
generation_id = enqueue.json()["generations"][0]["generation_id"]
while True:
resp = requests.get(
f"https://hub.oxen.ai/api/ai/queue/{generation_id}",
headers=HEADERS,
)
if resp.status_code == 404:
break
time.sleep(5)
print("Done. See the 'Async with SSE' tab to receive the result URL.")
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": "gpt-image-2-edit",
"prompt": "Place the subject on the surface of the moon with Earth rising in the background, photorealistic, cinematic lighting.",
"input_image": [
"https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png"
]
}' | 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": "gpt-image-2-edit",
"prompt": "Place the subject on the surface of the moon with Earth rising in the background, photorealistic, cinematic lighting.",
"input_image": [
"https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png"
]
},
)
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": "gpt-image-2-edit",
"prompt": "Place the subject on the surface of the moon with Earth rising in the background, photorealistic, cinematic lighting.",
"input_image": [
"https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png"
],
"resolution": "1024x1024",
"quality": "high",
"num_images": 1,
"output_format": "png"
}' | 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": "gpt-image-2-edit",
"prompt": "Place the subject on the surface of the moon with Earth rising in the background, photorealistic, cinematic lighting.",
"input_image": [
"https://hub.oxen.ai/api/repos/elau/assets/file/main/bloxy/bloxy_cropped_512x512.png"
],
"resolution": "1024x1024",
"quality": "high",
"num_images": 1,
"output_format": "png"
},
)
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/gpt-image-2-edit
Request parameters
Required parameters
| Field | Type | Default | Description |
|---|---|---|---|
prompt | string | "Place the subject on the surface of the moon with Earth rising in the background, photorealistic, cinematic lighting." | Text description of how to edit the input image(s). |
input_image | array<string> | — | One or more reference images to transform. Multiple URLs are composed together by the model. |
Optional parameters
| Field | Type | Default | Description |
|---|---|---|---|
resolution | string | "1024x1024" | Output image resolution. HD sizes (1920x1080 and lower) bill at the standard tier; QHD+ sizes (2560x1440 and higher) bill at the high-resolution tier. One of: 1024x768, 1024x1024, 1024x1536, 1920x1080, 2560x1440, 3840x2160. |
quality | string | "high" | Output quality tier. Locked to high for best fidelity. One of: high. |
num_images | integer | 1 | Number of images to generate per request. Range: 1 – 4. |
output_format | string | "png" | File format for the generated image. One of: png, jpeg, webp. |
mask_url | string | — | Optional mask image URL. White pixels mark regions to edit; black pixels are preserved. Leave empty to edit the whole image. Format: uri. |