Recraft erase, outpaint and inpaint calls vs one edit route on Sume
Recraft has separate inpaint, outpaint and erase calls. Sume has one /v1/images route with references and mask_url (ChatGPT Image 2.5 only), plus RMBG.

Recraft's docs list image to image, inpaint, outpaint and erase region as separate edits, plus background removal and replacement, vectorization at $0.01 and upscaling. Sume does not mirror that list. Its image edits go through one route, POST /v1/images, with reference images and, on ChatGPT Image 2.5 only, a mask_url. Erase and outpaint are not documented Sume operations, so for those two you describe the change in a prompt.
Operation map
Recraft's column is from its docs page (read 2026-10-05). Sume's is from the Sume Image API docs and catalog.
| Operation | Recraft | Sume |
|---|---|---|
| Image to image | Listed | input_references on POST /v1/images |
| Inpaint (mask) | Listed | mask_url, ChatGPT Image 2.5 only |
| Outpaint | Listed | Not a documented operation |
| Erase region | Listed | Not a documented operation; prompt the removal |
| Background removal | Listed | sume/rmbg-1.0, $0.0225 per image |
| Vectorization | $0.01 | Not documented |
| Upscaling | Listed | sume/image-upscale-1.0, $0.20 reserved per image |
One route, several knobs
A Sume edit is the same call as a generation with extra fields. input_references takes up to 10 images on most catalog models and 16 on ChatGPT Image 2.5. mask_url takes a public HTTPS mask. For other models, a mask_url returns 400 unsupported_parameter; Sume never silently drops a field.
Set aspect_ratio: "auto" on an edit to match the reference. The docs say that omitting the field is not the same as auto.
import asyncio, os, httpx
async def main():
body = {
"model": "openai/gpt-image-2.5",
"prompt": "Remove the person from the masked area and fill with the pavement behind.",
"input_references": [{"type": "image_url", "image_url": {"url": "https://example.com/street.png"}}],
"mask_url": "https://example.com/street-mask.png",
"aspect_ratio": "auto",
}
headers = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
async with httpx.AsyncClient(timeout=60) as c:
r = await c.post("https://api.sume.com/v1/images", headers=headers, json=body)
print(r.status_code, r.json().get("usage"))
asyncio.run(main())When to choose which
If your pipeline calls erase and outpaint as precise tools, Recraft's separate calls match it more closely. If your edits are mostly prompt-led and you want to keep one client, one key and one billing line, the single Sume route is simpler. Test a handful of your real erase jobs on both before you commit; this post compares documented features, not output quality. For the price side of cut-outs, see Recraft background operations against Sume RMBG.
A fair test
Take twenty real erase-and-extend jobs. Run them through Recraft's calls and through the Sume route with the same prompts. Count how many outputs you would ship without touching them, and divide the total cost by that number. That cost per usable image is a better comparison than either price list.
Sources
Related posts
More in Developers
- Redelivered job.completed must not start the trim twice
Redeliver re-sends the same job's terminal event with a fresh signature. Dedupe on job_id and derive the next step's Idempotency-Key from it.
- reference_ingest OCR: needs_verification crops under 0.85 confidence
reference_ingest never corrects OCR text. Lines under 0.85 confidence come back as needs_verification with a native-resolution crop to check.
- Reference-to-video with 3 images, 6 seconds: cost by Sume model
A 6-second reference-to-video clip with three images costs $0.45 on H3 at 768p up to $3.47 on Seedance 2.5 at 720p on Sume. Eight rows priced.
- Resume a video chain after a worker crash from stored job ids
Your worker died between generate and trim. Read the stored job id from /v1/jobs, do not resubmit paid work, and continue from the first step with no result.
Written by Sume