Model Library
Browse and deploy state-of-the-art AI models through the DEVUP Gateway.
Browse and deploy state-of-the-art AI models through the DEVUP Gateway.
FIBO Edit replaces prompt guessing with structured control. Instead of describing an edit in free-form text and hoping the model changes only what you meant, you supply a JSON blueprint that names lighting, composition, style, and camera settings explicitly — and the model changes those and nothing else. The same input produces the same output, which makes edits reproducible and auditable rather than probabilistic. Native mask support targets pixel-perfect regions while freezing the rest of the image. At eight billion parameters it is built for production pipelines, and it is trained exclusively on licensed data, which gives commercial teams something most image models cannot: legal clarity about what went into it.

An 8B-parameter image editing model that takes structured JSON instead of free-form text.
Ask a conventional editor for "a sunset" and it may also change the subject's face, shift the background texture, and warm the whole palette. You did not ask for any of that. You have no way to ask for less of it. And running the same prompt again gives you a different set of unwanted changes.
That is prompt roulette, and it is why image editing has stayed manual in most production pipelines.
FIBO Edit takes a different input. Rather than a sentence, it accepts a structured description that names visual elements separately — lighting, composition, style, camera parameters — so that changing one does not disturb the others.
Two properties follow, and both matter more in a pipeline than in a creative session:
Reproducibility. The same input produces the same output. An edit you approved last month regenerates identically today.
Auditability. The instruction is structured data, so it can be diffed, versioned, reviewed, and generated by code. What changed is legible without comparing images.
The technical term for what makes this work, and worth understanding before writing a request.
In a conventional model, "vintage" is a single entangled concept — it moves colour, grain, contrast, and lighting together because those moved together in the training captions. You cannot request one without the others.
FIBO Edit separates them. Camera angle is one field. Lighting is another. Style is a third. Setting
camera_angle to a low angle changes the camera angle — not the mood, not the palette, not the
subject's expression.
The practical consequence: you can iterate on one dimension at a time. Fix the lighting, approve it, then adjust the composition without losing the lighting you just approved. On a conventional model each change is a fresh roll of the dice.
Native mask support, and the rule is simple: white areas are edited, everything else is frozen.
Supply a black-and-white mask alongside the source image and the model regenerates only the marked region. This is what separates changing a sign above a door from regenerating a storefront that happens to have a different sign.
Combined with structured prompting, masking gives two independent axes of control: where the edit applies, and what specifically changes within it.
Beyond localised edits, mask support covers generative fill and outpainting — extending an image past its original frame.
This is the reason enterprise teams choose it, and it has nothing to do with output quality.
FIBO Edit is trained exclusively on fully licensed, rights-cleared data. For a company shipping generated imagery in a product, an advertisement, or a publication, that provenance is the difference between a legal question with an answer and one without.
Read the licence for your specific deployment carefully. Training-data provenance and weight licensing are separate questions, and the terms attached to the published weights may differ from the terms available through a commercial arrangement. Clean training data does not automatically mean unrestricted commercial use of the weights.
| Model ID | Bria/fibo_edit-1.5 |
| Parameters | 8B |
| Input | Image, structured prompt, optional mask, optional reference images |
| Output | Image |
| Masking | Native — white areas edited |
| Determinism | Same input produces the same output |
| Training data | Fully licensed |
| Endpoint | /v1/images/edits |
A technical report has been announced and is not yet published.
| Capability | Value |
|---|---|
input_types | image, text |
output_types | image |
mask_editing | Supported |
generative_fill | Supported |
outpainting | Supported |
multi_image_input | Supported |
negative_prompt | Supported |
structured_prompt | Supported — JSON |
deterministic | Yes, for a fixed input |
endpoint | /v1/images/edits |
requires_prompt | Yes — source image and instruction required |
In its default configuration, Bria routes natural-language instructions through a vision-language model that translates them into the structured format the editor consumes.
Two things follow.
You can write plainly if you want to. "Change the lighting to neon cyberpunk" works — it is translated before it reaches the editor.
Writing the structure yourself is more deterministic. The translation step is where ambiguity enters. If reproducibility is the reason you chose this model, supplying the structured form directly removes the only non-deterministic component in the path.
For automated pipelines and agents generating edits programmatically, structured input is the natural form anyway — code produces JSON more reliably than it produces prose.
Endpoint: POST https://api.devupai.com/v1/images/edits
The response returns a signed URL in data[0].url alongside a _devup object carrying the request
cost and your remaining balance.
The URL is valid for five minutes. Fetch the image within that window.
import os
import requests
from pathlib import Path
DEVUP_API_KEY = os.environ["DEVUP_API_KEY"]
EDIT = "https://api.devupai.com/v1/images/edits"
def edit(image_path: Path, prompt: str, *, mask_path: Path | None = None, seed: int | None = None) -> bytes:
"""Apply an edit to an image, optionally restricted to a masked region."""
files = {"image": image_path.open("rb")}
if mask_path is not None:
files["mask"] = mask_path.open("rb")
data = {"model": "Bria/fibo_edit-1.5", "prompt": prompt}
if seed is not None:
data["seed"] = seed
try:
response = requests.post(
EDIT,
headers={"Authorization": f"Bearer {DEVUP_API_KEY}"},
files=files,
data=data,
timeout=300,
)
response.raise_for_status()
result = response.json()
finally:
for handle in files.values():
handle.close()
spend = result.get("_devup", {})
print(f"{spend.get('cost_dzd')} DZD · balance {spend.get('balance_dzd')}")
# The URL is valid for five minutes.
return requests.get(result["data"][0]["url"], timeout=120).content
Path("edited.png").write_bytes(
edit(Path("product.png"), "Change the background to a pale grey seamless studio backdrop.")
)Path("storefront_edited.png").write_bytes(
edit(
Path("storefront.png"),
'A hand-painted wooden board reading "ATLAS" in cream capitals.',
mask_path=Path("sign_mask.png"),
)
)The mask is black and white. White marks what changes; everything else is preserved exactly. A soft or anti-aliased edge produces a soft transition, which is usually what you want on an organic boundary and not what you want on a hard edge like a sign.
Where the model's actual design shows.
import json
blueprint = {
"lighting": {
"type": "neon",
"direction": "side",
"intensity": "high",
"color_temperature": "cool",
},
"camera": {
"angle": "low_angle",
"focal_length": "35mm",
},
"style": {
"aesthetic": "cyberpunk",
"grain": "subtle",
},
"preserve": ["subject_identity", "composition", "background_geometry"],
}
Path("restyled.png").write_bytes(
edit(Path("portrait.png"), json.dumps(blueprint), seed=42)
)Each field moves one dimension. Changing camera.angle does not touch the lighting; changing
lighting.intensity does not touch the style. That independence is the entire argument for the
model.
The preserve list states explicitly what must not move. Naming what stays is as useful as naming
what changes — on any editing model, and particularly on one built for reproducible pipelines.
Field names above are illustrative. Consult the current structured-prompt reference for the exact schema before building around specific keys.
The workflow determinism makes possible.
BASE = Path("product_hero.png")
SEED = 1337
variants = {
"warm": {"lighting": {"color_temperature": "warm", "intensity": "medium"}},
"cool": {"lighting": {"color_temperature": "cool", "intensity": "medium"}},
"dramatic": {"lighting": {"color_temperature": "neutral", "intensity": "high", "direction": "side"}},
}
for name, blueprint in variants.items():
Path(f"hero_{name}.png").write_bytes(
edit(BASE, json.dumps(blueprint), seed=SEED)
)Same source, same seed, one field changing between runs. Any difference in the output is attributable to the field you changed — which is what makes a comparison meaningful rather than anecdotal.
On a conventional editing model this experiment does not work: the sampler moves between runs, and you cannot separate your change from the noise.
response = requests.post(
EDIT,
headers={"Authorization": f"Bearer {DEVUP_API_KEY}"},
files={"image": open("scene.png", "rb")},
data={
"model": "Bria/fibo_edit-1.5",
"prompt": "Replace the background with an outdoor market at midday.",
"negative_prompt": "people, text, signage, motion blur",
"seed": 42,
},
timeout=300,
)Negative prompts specify what to keep out. On a background replacement this is frequently the difference between a usable plate and one full of incidental detail you then have to mask away.
import { writeFile } from "node:fs/promises";
import { createReadStream } from "node:fs";
const form = new FormData();
form.append("model", "Bria/fibo_edit-1.5");
form.append("prompt", "Change the background to a pale grey seamless studio backdrop.");
form.append("image", new Blob([await readFile("product.png")]), "product.png");
const response = await fetch("https://api.devupai.com/v1/images/edits", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.DEVUP_API_KEY}` },
body: form,
signal: AbortSignal.timeout(300_000),
});
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
const result = await response.json();
// The URL is valid for five minutes.
const image = await fetch(result.data[0].url);
await writeFile("edited.png", Buffer.from(await image.arrayBuffer()));Pin the seed while iterating. With a fixed seed, a difference in output is attributable to your change rather than to sampling. This is the single most useful habit on this model and the one most often skipped.
Change one field at a time. Disentangled control is only useful if you exercise it one dimension at a time. Rewriting the whole blueprint between attempts discards the advantage.
Name what to preserve, not only what to change.
Use masks for spatial precision, structure for attribute precision. They are independent controls, and combining them gives the tightest result available.
Start simple and add structure. A plain instruction establishes whether the model understands the goal. Structure then makes that result repeatable.
Store the blueprint alongside the output. The instruction is the reproducible artefact — with the source image and the seed, it regenerates the result exactly. That is what makes an edit auditable months later.
Use high-quality source images. Editing amplifies whatever is already there; a compressed or low-resolution source limits the ceiling regardless of the model.
Automated production pipelines. Code generating edits programmatically produces structured data naturally, and needs the output to be predictable.
Agent-driven workflows. An agent adjusting one visual attribute at a time needs a control surface where one adjustment does not disturb the rest.
Enterprise and regulated content. The licensed training data is the reason, and for some organisations it is the only reason that matters.
Product imagery at scale. One approved photograph, many controlled variations, each reproducible.
Anything requiring an audit trail. A structured instruction is a record of what was changed; a text prompt and an image are not.
Less suited to open-ended creative exploration, where the looseness of a conventional model is a feature rather than a defect.