# GPT Image 2.5 Inpaint (image-edit) > GPT Image 2.5 Inpaint changes one masked region of an image and keeps every other pixel. It is the roasOS positional edit: replace a label, remove an object, fill a gap. It runs fal's sunburst editor. Status: roasOS API v1.1. Catalog `model-catalog@2026-10-06.v5`, pricing `customer-pricing@2026-11-05.v15`. The endpoint `POST /v1/image-edit/gpt-image-2.5` is live. `POST /v1/generations` has no `image-edit` type, so this endpoint is the only path to this model. ## Endpoint POST https://api.roasos.com/v1/image-edit/gpt-image-2.5 Auth: Authorization: Bearer roasos_sk_… (scope api:write). Idempotency-Key required. quote_only / quote_id / webhook_url as in https://docs.roasos.com/llms.txt. ## Good at GPT Image 2.5 Sunburst makes "edits scoped precisely to the instruction, with subject and composition preserved across many rounds of revision". Use this endpoint when one region must change and the rest of the picture must stay exactly as it is: replace a label, remove an object, open a closed door. The mask states which region to edit. The output is one PNG at `high` quality, at the source dimensions and with the source background (`background` is pinned to `auto`). Use /v1/image/gpt-image-2.5 in edit mode when the whole image may change, and /v1/image/nano-banana-pro when identity or product placement matters. Do not use it for a whole-image restyle; the mask has meaning against one source only. ## Pricing Unit: operation. Pricing key: `gpt-image-2.5-inpaint`. | request | credits | |---|---| | `1_image` | 7 | Credits come from the roasOS pricing table (`MODEL_COSTS`) through the catalog. No other field changes the price. ## Modes - `inpaint` Provider endpoints: `openai/gpt-image-2.5/sunburst/edit`. ## Request fields | field | type | required | default | rule | |---|---|---|---|---| | `image_url` | string | yes | — | https URL; ≤ 4,096 characters | | `mask_url` | string | yes | — | https URL; ≤ 4,096 characters | | `prompt` | string | yes | — | ≥ 1 character; ≤ 10,000 characters | | `quote_id` | string | no | — | UUID | | `quote_only` | boolean | no | `false` | — | | `wait_timeout_seconds` | integer | no | `0` | 0–60 | | `webhook_url` | string | no | — | https URL; ≤ 4,096 characters | The schema is strict: a field that is not in this table returns `400 unsupported_option`. Field names are the roasOS role names, one name per role across every family. ## Media - `image_url` — first frame (or the single source image) | role | items | max size | content types | duration | |---|---|---|---|---| | `image_url` | ≤ 1 | 10 MB | `image/jpeg`, `image/png`, `image/webp` | — | | `mask_url` | ≤ 1 | 10 MB | `image/png` | — | - Refused: `avatar_id`, `elements`, `product_id`, `product_images`, `references`, `reference_images`, `end_image_url`, `scene_id`, `scene_image`, `video_urls`, `video_url`, `audio_urls`, `audio_url`, `voice_id`. A refused role returns `400 unsupported_option`. - Every URL must be an immutable object on `https://cdn.roasos.com/…` that your workspace owns; any other URL is `400 reference_media_not_workspace_owned`. Upload with `POST /v1/uploads` (direct POST of the bytes to `put_url`, or a `source_url` import), then use the returned CDN URL. ## Prompt Limit: 10,000 characters. No wrapper is added. No tag syntax. - Describe the finished content of the masked region, not the mask ("a matte black label with the words \"Slow Evenings\" in cream cursive"). - Name the material, the light direction and the perspective so the region matches the rest of the picture. - Put rendered text inside quotation marks. - Do not describe the parts of the image outside the mask; they do not change. - On a bad result, adjust the mask or the prompt; do not resend the same payload. ## Not exposed - `background`: pinned to `auto`. - `image_size`: pinned to `auto`. - `num_images`: pinned to `1`. - `output_compression`: not accepted by this public endpoint. - `output_format`: pinned to `png`. - `quality`: pinned to `high`. - `sync_mode`: pinned to `false`. ## Result Result kind `image`. Always present: nothing. Present when the run produces it: `avatar_id`, `full_body_url`, `images`, `portrait_url`, `provider_seed`, `reference_sheet`, `url`. ```json { "data": { "id": "gen_…", "kind": "image", "model": "gpt-image-2.5", "status": "completed", "result": {"avatar_id":"00000000-0000-4000-8000-000000000000","full_body_url":"https://cdn.roasos.com/workspaces/ws_01/full_body_url","images":["https://cdn.roasos.com/workspaces/ws_01/images-1.png"],"portrait_url":"https://cdn.roasos.com/workspaces/ws_01/portrait_url","provider_seed":0,"reference_sheet":"https://cdn.roasos.com/workspaces/ws_01/reference_sheet","url":"https://cdn.roasos.com/workspaces/ws_01/result"} } } ``` Files live on `https://cdn.roasos.com` and are immutable; a result URL can be a media input to the next call. Poll `GET /v1/jobs/{id}/status` → `{ id, status, updated_at }`, then `GET /v1/jobs/{id}/result` (`409 run_not_completed` until the job is `completed`, `failed` or `canceled`). Statuses: `queued → processing → completed | failed | canceled`. ## Example ```bash # 1. quote — nothing is spent curl -X POST https://api.roasos.com/v1/image-edit/gpt-image-2.5 \ -H "Authorization: Bearer roasos_sk_live_…" \ -H "Idempotency-Key: 0f1c9e2a-gpt-image-2.5-0001" \ -H "Content-Type: application/json" \ -d '{"quote_only":true,"image_url":"https://cdn.roasos.com/workspaces/ws_01/uploads/image_url.png","mask_url":"https://cdn.roasos.com/workspaces/ws_01/uploads/mask_url.png","prompt":"A woman holds the bottle at eye level in a bright kitchen, morning light, static camera."}' # → 200 { "data": { "kind": "quote", "quote_id": "q_7Hk…", "credits": 7, "expires_at": "…", "confirmation": { "model": "gpt-image-2.5", "example": "1_image" } } } # 2. run — the same body and the same Idempotency-Key, quote_id instead of quote_only curl -X POST https://api.roasos.com/v1/image-edit/gpt-image-2.5 \ -H "Authorization: Bearer roasos_sk_live_…" \ -H "Idempotency-Key: 0f1c9e2a-gpt-image-2.5-0001" \ -H "Content-Type: application/json" \ -d '{"quote_id":"q_7Hk…","image_url":"https://cdn.roasos.com/workspaces/ws_01/uploads/image_url.png","mask_url":"https://cdn.roasos.com/workspaces/ws_01/uploads/mask_url.png","prompt":"A woman holds the bottle at eye level in a bright kitchen, morning light, static camera."}' # → 201 { "data": { "id": "gen_…", "kind": "image", "model": "gpt-image-2.5", "status": "queued", "credits_reserved": 7, "links": { "status": "/v1/jobs/gen_…/status", "result": "/v1/jobs/gen_…/result" } } } # 3. poll curl https://api.roasos.com/v1/jobs/gen_…/status -H "Authorization: Bearer roasos_sk_live_…" curl https://api.roasos.com/v1/jobs/gen_…/result -H "Authorization: Bearer roasos_sk_live_…" ``` ## Today `POST /v1/image-edit/gpt-image-2.5` is live. `POST /v1/generations` has no `inpaint` type, so this endpoint is the only public surface. The endpoint measures the source and the mask before the quote. The mask must have the same width and height as the source. A mask of another size gets `400 unsupported_media`. The source is JPEG, PNG or WebP; the mask is PNG. White marks the region to edit. The retired `/v1/image-edit/gpt-image-2` answers 404. ## See also https://docs.roasos.com/models/image-edit/gpt-image-2.5 · https://api.roasos.com/v1/catalog/image-edit/gpt-image-2.5 · openai/gpt-image-2.5/sunburst/edit