DEV Community

Om Prakash
Om Prakash

Posted on

Edit a Whole Real-Estate Listing in One API Call

Real-estate photos are a volume problem. A single listing is 20–40 photos. A busy agent or property photographer shoots several listings a week. Every one of those photos needs the same boring treatment: fix the white balance, lift the dark interiors, straighten the wide-angle tilt, and — for the exterior shots — turn that flat grey sky into something a buyer actually wants to click on.

Doing that one photo at a time in Lightroom or Photoshop is hours of work per listing. So we built an endpoint that takes the whole listing at once.

The idea: send a folder, get a folder back

PixelAPI's real-estate batch endpoint is deliberately simple. You zip up a folder of property photos, POST it in a single request, and the response is the processed zip. No job IDs, no polling loop, no webhooks to wire up. It's synchronous: you send 10–50 photos and the listing-ready versions come straight back.

Under the hood each photo gets a non-destructive pass:

  • Every photo: white balance, contrast, and a gentle colour boost — the whole scene is kept, nothing is cut out.
  • Exteriors only: the real sky is detected and replaced with a clean blue gradient, feathered at the rooflines so clouds and edges are preserved.
  • Safety: if no genuine sky is found, the photo is just enhanced — so an interior shot can never get accidentally painted blue.

The result: brighter, consistent, listing-ready photos for the entire property in seconds.

Call it from code

Here's the whole integration. Zip the folder, send it, unzip the response.

import io
import os
import zipfile
from pathlib import Path

import requests

API_KEY = os.environ["PIXELAPI_KEY"]
ENDPOINT = "https://api.pixelapi.dev/v1/real-estate/batch-process"

PRODUCTS = Path("products")
OUTPUT = Path("output")
OUTPUT.mkdir(exist_ok=True)

# 1. Bundle every property photo into one zip (in memory).
photos = sorted(
    p for p in PRODUCTS.iterdir()
    if p.suffix.lower() in {".jpg", ".jpeg", ".png"}
)
buf = io.BytesIO()
with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as zf:
    for photo in photos:
        zf.write(photo, arcname=photo.name)
buf.seek(0)

# 2. Send the whole batch in a single request.
resp = requests.post(
    ENDPOINT,
    headers={"Authorization": f"Bearer {API_KEY}"},
    files={"file": ("listing.zip", buf, "application/zip")},
    timeout=600,
)
resp.raise_for_status()

# 3. The response IS the processed zip — unzip it straight into output/.
with zipfile.ZipFile(io.BytesIO(resp.content)) as zf:
    for name in zf.namelist():
        (OUTPUT / Path(name).name).write_bytes(zf.read(name))

print(f"Done. {len(photos)} listing-ready photos in output/")
Enter fullscreen mode Exit fullscreen mode

Prefer curl?

curl -X POST https://api.pixelapi.dev/v1/real-estate/batch-process \
  -H "Authorization: Bearer $PIXELAPI_KEY" \
  -F "file=@listing_raw.zip" \
  --output listing_ready.zip
Enter fullscreen mode Exit fullscreen mode

That's the entire contract. One multipart POST with a zip of photos, one zip of processed photos back.

Don't want to write code?

There's a web tool too. Sign in, drag in a zip of property photos, and run a real batch against the same live API — the before/after results come straight back in the browser, and you can download the finished listing as a zip. Same engine, no integration required.

Who this is for

  • Real estate agents & brokerages — prep an entire MLS / Zillow / Rightmove listing in one upload.
  • Property photographers — post-process a full 30–40 frame shoot automatically and deliver the same day.
  • Short-term rental hosts — batch-clean every room into consistent, bright listing images.
  • Proptech & listing portals — auto-enhance every agent-uploaded photo at ingest, so listings look uniform across thousands of properties.

See it run end to end

We recorded a full walkthrough — real sign-in, a real zip upload, the live API call, the before/after results for every photo, and the same job driven from a Python script. No slides, no faked output.

▶️ Watch the tutorial: https://youtu.be/4lgKyCByMs8

Try it free

You get 100 free credits, no credit card to run your first listings.

If you batch-process property photos for a living, this is the boring-but-essential step you can stop doing by hand.

Top comments (1)

Collapse
 
harjjotsinghh profile image
Harjot Singh

Collapsing a multi-step listing edit into one atomic API call is a nice API-design win, and the part worth emphasizing is the atomicity, not just the convenience. The danger with "edit the whole listing at once" is partial failure - if you update photos, price, and description in one call and the price write succeeds but the description fails, you've left the listing in a corrupt half-updated state. So the real engineering behind a good one-call-edit is transactional: it all applies or none of it does, with validation up front so a bad field rejects the whole payload instead of half-writing it. That's what makes "one API call" safe rather than just compact.

That all-or-nothing, validate-before-you-commit instinct is the same discipline I lean on in Moonshift, the thing I work on - a multi-agent pipeline that takes a prompt to a deployed SaaS, where changes are validated and gated before they apply rather than partially written. Same principle: a single operation should leave the system consistent, never half-done. Multi-model routing keeps a build ~$3 flat, first run free no card. Clean API design. Is the one-call edit transactional/atomic under the hood, or does it apply field-by-field? The partial-failure handling is the thing I'd hammer on before trusting it in prod.