flux-1-fill-pro is hiapi's mask-based inpainting model: you send a source image, a black-and-white mask and a prompt, and only the white area is repainted. This guide gives a working curl and Python request, the async flow, and what one real run showed about the mask boundary and output size. You need an API key from the dashboard.
Request shape
The model runs on the unified task API. Create a task with POST https://api.hiapi.ai/v1/tasks, poll GET /v1/tasks/<taskId>, and read data.output[0].url. The inputs below come from the model page and the API docs:
| Field | Type | Notes |
|---|---|---|
input.image | URL, required | Source image. JPEG, PNG, GIF or WebP. |
input.mask | URL, required | Black keeps the source, white is repainted. Must match the source dimensions. |
input.prompt | string, required | Describe the new content inside the white area. Up to 4,000 characters. |
input.steps | int, 15–50 | Default 50. |
input.guidance | number, 1.5–100 | Default 60. |
input.seed | int | Fixed seed with identical inputs gives a consistent result. |
input.output_format | jpg | png | Default jpg. |
input.prompt_upsampling | bool | Default false. Leave it off to keep your exact wording. |
Both image and mask are URLs, not base64 or file uploads. Host them somewhere the API can fetch over http(s).
Minimal curl request
curl -s https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer $HIAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "flux-1-fill-pro",
"input": {
"image": "https://dev-static.hiapi.ai/model-onboarding/flux-1-fill-pro/2026/10/19/2026/10/19/1792418738578-4e5072a121d7018f-source.jpg",
"mask": "https://dev-static.hiapi.ai/model-onboarding/flux-1-fill-pro/2026/10/19/2026/10/19/1792418739459-82bb18075f29c864-mask.png",
"prompt": "A large framed oil landscape of a misty mountain lake at dawn, thin black frame, hanging flat on the wall; keep the sofa, floor and lighting unchanged.",
"steps": 30,
"guidance": 60,
"seed": 42,
"output_format": "png"
}
}'
The response is {"code":200,"data":{"taskId":"tk-hiapi-..."},"message":"success"}. Poll that ID until data.status is success or fail.
Python: create, poll, download
import os, time, requests
API = "https://api.hiapi.ai"
HEADERS = {"Authorization": f"Bearer {os.environ['HIAPI_KEY']}"}
def inpaint(image_url, mask_url, prompt, **opts):
body = {"model": "flux-1-fill-pro",
"input": {"image": image_url, "mask": mask_url, "prompt": prompt, **opts}}
r = requests.post(f"{API}/v1/tasks", headers=HEADERS, json=body, timeout=30)
r.raise_for_status()
task_id = r.json()["data"]["taskId"]
while True:
try:
d = requests.get(f"{API}/v1/tasks/{task_id}", headers=HEADERS, timeout=20).json()["data"]
except requests.RequestException:
time.sleep(5) # transient network error: poll the same taskId again
continue
if d["status"] == "success":
return d["output"][0]["url"]
if d["status"] == "fail":
raise RuntimeError(d.get("error", d))
time.sleep(5)
url = inpaint(
"https://example.com/room.jpg",
"https://example.com/room-mask.png",
"A framed landscape painting, thin black frame; keep the room unchanged.",
steps=30, seed=42, output_format="png",
)
open("out.png", "wb").write(requests.get(url, timeout=60).content)
Download the result right away. The output URL carries an expireAt and the file is temporary storage, so do not store the link as the permanent address.
Production notes
- Poll or callback. For batch jobs, add
"callback": {"url": "https://your-domain.com/hiapi/callback", "when": "final"}to the task body, and use the task ID to deduplicate notifications. Keep polling as a fallback. - Retry the poll, not the create. A new
POSTcreates and bills a new task. If one poll request errors out, poll the sametaskIdagain. - Keep the mask next to the source. The mask has to match the source dimensions exactly, so generate it from the same file (polygon tool, segmentation output) instead of resizing a screenshot.
- Fix the seed while tuning. Use one seed and change only
stepsorguidance, so each difference comes from that parameter.
Per-image cost is on the pricing page, so check it before running large catalogs.
What one real run showed
I ran the curl request above once against the page's own example room photo (1600×900) and its rectangular mask (white box at x 840–1240, y 160–580). Settings were steps: 30, guidance: 60, seed: 42, output_format: png.
- Timing. The task went
handlingfor about 25 s, thenarchiving, and reachedsuccessin about 38 s end to end. - Output size differs from the source. The returned PNG was 1440×810, not 1600×900. The aspect ratio matched, but the pixel size did not. If you composite the result back onto the original, resize one of them first and do not assume 1:1.
- Outside the mask stays put. After scaling the source to 1440×810 and diffing against the output, 81% of pixels inside the white box changed by more than 8 levels (0–255), while only 0.03% of the pixels outside it did. More than 12 px from the mask edge, the largest difference was 11 levels. The sofa, cushions, plant, floor and window light were not repainted.
- Prompt scope. The prompt described only the painting and what to preserve, and the result is a framed mountain-lake scene that fills the white box.
- A bad URL fails on the poll, not on create. A separate request with
imageandmaskset to a non-URL string returned200and ataskId, then the task ended withstatus: failanderror.code: TASK_FAILEDabout 3 seconds later. YourPOSTsucceeding does not mean your inputs were valid, so always check the terminal state.
Not tested: mismatched mask and source dimensions, masks with grey (soft-edge) values, alpha-channel masks, and guidance or steps extremes. The docs say the mask must match the source size, and I only tested a hard two-value rectangle. I did not run more than one seed, so I cannot say how much the fill varies from run to run.
When to pick Fill Pro
Use it when the edit has to stop at a hard boundary you control, such as a product label, a wall line or a garment seam. For edits you describe in words with no mask, use a prompt-only model. The image inpainting and object removal guide compares those. To erase something from a mask without writing a prompt, see the Bria Eraser guide.
Related
- FLUX.1 Fill Pro model page
- flux-1-fill-pro API reference
- Pricing
- How to use the Bria Eraser API
- FLUX.2 image-to-image guide
FAQ
Are both image and mask required?
Yes. The current docs list image, mask and prompt as required.
Which color does the model repaint?
White. Black pixels keep the source.
Does the mask need to be the same size as the source?
The docs say so. I used a matching pair in my run, and I did not test a mismatched one.
What does the output look like in size?
In my run a 1600×900 source returned a 1440×810 PNG with the same aspect ratio.





