AI roof color preview: try shingle colors on a photo of your house

Try charcoal, brown or green shingles on a photo of your house: mask the roof, pass a shingle sample as a second reference, and compare options with Sume edits.

4 min readSume
All posts

Mask only the roof

A roof is the largest color on most houses and the hardest to imagine from a catalog card. Mask the roof area on your photo, add a photo of the shingle sample as the second reference, and ask for the roof only.

mask_url is a ChatGPT Image 2.5 field in Sume's catalog; other models reject it with 400 unsupported_parameter. The roof mask keeps gutters, chimneys and sky out of the edit.

Sume Image API docs list ChatGPT Image 2.5 as openai/gpt-image-2.5 (Flare) and openai/gpt-image-2.5-sunburst. OpenAI's guide says to choose Sunburst where editing precision matters most and Flare for fast everyday generation, so these edits use Sunburst.

Name what must not move

Say the roof pitch, ridge line, chimney, vents and gutters stay as photographed, and that only shingle color and texture change. Name the sample as image 2 and the house as image 1.

import os
import requests

REFS = [
    "https://example.com/house.jpg",
    "https://example.com/shingle.jpg",
]
resp = requests.post(
    "https://api.sume.com/v1/images",
    headers={"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"},
    json={
        "model": "openai/gpt-image-2.5-sunburst",
        "prompt": "Image 1 is a house photo, image 2 is a shingle sample. "
                  "Recolor the roof surface with image 2 only. Keep the roof "
                  "shape, chimney, vents, gutters, walls and sky unchanged.",
        "aspect_ratio": "auto",
        "mask_url": "https://example.com/roof-mask.png",
        "input_references": [
            {"type": "image_url", "image_url": {"url": u}} for u in REFS
        ],
    },
    timeout=60,
)
print(resp.status_code)
print(resp.json())

Three samples, three calls

Swap the sample file, keep the photo and mask the same.

Shingle options to compare (example inputs; request rules per Sume docs, read 2026-10-03)
OptionSample
ACharcoal
BWeathered wood brown
CForest green

Judge in the light you will see it

Roofs look different under cloud and in low sun. Take the source photo in the light you usually see the house in, and ask your roofer for a physical sample to hold up against the wall.

Inputs Sume checks before it spends anything

Reference and mask URLs must be public HTTPS; localhost, private-network and non-HTTPS URLs are rejected. Sume also checks every field against the model's catalog entry, so a field the model does not list returns 400 unsupported_parameter instead of being dropped without a word.

If you are unsure which fields a model accepts, GET /v1/images/models lists them, and GET /v1/images/models/{id}/endpoints returns the per-endpoint capabilities and pricing.

Timing and what a call costs

POST /v1/images on Sume waits up to 30 seconds and returns 200 with the image. If the generation is still running at that point you get 202 and a job envelope with a status URL and a result URL instead. The docs name 4K, high quality and large n as the settings most likely to degrade to 202, so branch on the status code, not on the body shape.

Billing is all-or-nothing. A completed generation is billed in full, a failed or cancelled one is not, and usage.cost in the response is the USD amount charged: the provider list price times 1.25.

Sources

Related posts

More in Use cases

All Use cases posts

Written by Sume