Documentation

Real Estate: MLS Compliance & Listings

Upload property photos, check MLS compliance, manage listings, and automate photo ordering with AI

Prerequisites

Before using the MLS features, make sure you have installed the SDK or have your API key ready. Photos must be uploaded with content_category="real_estate" to enable property feature extraction and compliance analysis.

Two Workflows

Scopix offers two approaches to MLS compliance, depending on your use case:

Ad-Hoc Compliance

Quick, stateless checks on a set of image IDs. No listing required. Results are returned but not persisted. Use POST /mls/check or POST /mls/listings/analyze.

Listing Management

Create persistent listings, attach photos, run compliance analysis, and track results over time with snapshots. Full CRUD under /mls/listings.

Step 1: Upload Real Estate Photos

Upload listing photos with the real_estate content category. The AI automatically extracts room type, architectural style, materials, condition, and more.

python
from scopix import Scopix, ContentCategory
async with Scopix(api_key="scopix_...") as client:
result = await client.files.upload(
"kitchen.jpg",
content_category=ContentCategory.REAL_ESTATE,
)
print(f"Image ID: {result.image_id}")
print(f"Description: {result.description}")
# Real estate extraction data is available in the file details
file = await client.files.get(result.image_id)
print(f"Real estate data: {file.real_estate_data}")

What Gets Extracted

When you upload with content_category="real_estate", the vision model extracts structured property data:

Photo Classification

  • Image context (exterior_front, interior_room, aerial, floor_plan, etc.)
  • Room type (kitchen, bedroom, bathroom, living_room, etc.)

Property Features

  • Architectural style, exterior materials, roof type
  • Flooring, countertops, cabinetry, fixtures

Condition & Quality

  • Overall condition (excellent/good/fair/poor)
  • Renovation status, staging quality, finish level

Marketing

  • Up to 5 AI-generated selling points per photo
  • Design style classification

See the Image Uploads guide for full upload options including batch and directory uploads.

Step 2: Check Supported MLS Standards

Scopix supports four MLS standards, each with unique rules for photo requirements.

Supported Standards

nar_baselineNAR Baseline — US MLS common baseline. 1–50 photos. No watermarks, agent branding, or contact info.
crmlsCalifornia Regional MLS — 1–75 photos. Prohibits For Sale signs. Includes CA AB 723 virtual staging disclosure rules.
nwmlsNorthwest MLS — 1–40 photos. Strictly prohibits people and pets in photos.
bright_mlsBright MLS (Mid-Atlantic) — 1–75 photos. No sky replacement or element alteration outside property control.

List Standards

Retrieve all supported standards and their configurations.

python
import requests
response = requests.get(
"https://api.scopix.ai/api/v2/mls",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
standards = response.json()["standards"]
for s in standards:
print(f"{s['id']}: {s['name']} ({s['min_photos']}-{s['max_photos']} photos)")

Get Standard Requirements

View detailed rules for a specific standard.

python
response = requests.get(
"https://api.scopix.ai/api/v2/mls/crmls/requirements",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
reqs = response.json()
print(f"Standard: {reqs['mls_standard_name']}")
print(f"Rules: {reqs['rule_count']}")
for rule in reqs["rules"]:
print(f" [{rule['severity']}] {rule['name']} ({rule['rule_type']})")

Step 3: Ad-Hoc Compliance Check

Check photos against an MLS standard without creating a listing. Returns per-photo pass/fail results with actionable remediation.

Check Photo Compliance

Pass up to 200 image IDs and an MLS standard. Each photo is checked against the standard's rules.

python
import requests
response = requests.post(
"https://api.scopix.ai/api/v2/mls/check",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"image_ids": ["IMAGE_UUID_1", "IMAGE_UUID_2"],
"mls_standard": "crmls",
},
)
data = response.json()
print(f"Standard: {data['mls_standard']}")
print(f"Compliant: {data['compliant_count']}/{data['total_images']}")
for result in data["results"]:
status = "PASS" if result["compliant"] else "FAIL"
print(f" [{status}] {result['image_id']} — quality: {result['quality_score']}/100")
for rem in result["remediation"]:
print(f" Fix: {rem['fix']}")

Stateless

Ad-hoc checks are not persisted. Use the Listing Management workflow below to save compliance results as snapshots and track them over time.

Example Response

json
{
"mls_standard": "crmls",
"total_images": 2,
"compliant_count": 1,
"non_compliant_count": 1,
"results": [
{
"image_id": "abc-123",
"mls_standard": "crmls",
"compliant": true,
"quality_score": 87,
"total_checks": 11,
"passed_checks": 11,
"failed_checks": 0,
"checks": [
{ "rule_name": "min_width", "passed": true, "severity": "error", "message": "..." }
],
"remediation": []
},
{
"image_id": "def-456",
"mls_standard": "crmls",
"compliant": false,
"quality_score": 62,
"total_checks": 11,
"passed_checks": 9,
"failed_checks": 2,
"checks": [...],
"remediation": [
{
"rule_name": "no_watermarks",
"severity": "error",
"issue": "Watermark detected in the photo",
"fix": "Remove all watermarks from the photo.",
"current_value": true,
"required_value": false
}
]
}
]
}

Step 4: Full Listing Analysis

Go beyond per-photo checks. Analyze a complete set of listing photos for compliance, quality, ordering, completeness, and duplicates in one call.

Analyze Listing Photos

python
response = requests.post(
"https://api.scopix.ai/api/v2/mls/listings/analyze",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"image_ids": ["IMG_1", "IMG_2", "IMG_3", "IMG_4", "IMG_5"],
"mls_standard": "nar_baseline",
},
)
analysis = response.json()
print(f"Quality Score: {analysis['listing_quality_score']}/100")
print(f"Completeness: {analysis['completeness_score']}/100")
print(f"Compliant: {analysis['compliant_photos']}/{analysis['total_photos']}")
# Recommended photo order for MLS
print("\nRecommended Order:")
for photo in analysis["ordered_photos"]:
print(f" {photo['image_context']}: {photo['image_id']} (quality: {photo['quality_score']})")
# Missing photo types
if analysis["missing_photo_types"]:
print(f"\nMissing: {', '.join(analysis['missing_photo_types'])}")
# Actionable recommendations
for rec in analysis["recommendations"]:
print(f" → {rec}")

Canonical Photo Order

The analysis returns photos sorted into the order MLSs expect. Within each category, photos are ranked by quality score (highest first).

1. exterior_front → 2. exterior_side → 3. exterior_rear → 4. aerial

5. kitchen → 6. living_room → 7. dining_room → 8. family_room

9. bedroom → 10. bathroom

12. office → 13. laundry → 14. basement → 15. attic

16. hallway → 17. entryway → 18. closet → 19. garage_interior

20. amenity → 21. neighborhood → 22. floor_plan → 23. detail_shot → 24. other

Step 5: Persistent Listing Management

Create listings, attach photos, run compliance analysis, and track results over time.

Create a Listing

python
response = requests.post(
"https://api.scopix.ai/api/v2/mls/listings",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"name": "123 Main Street",
"mls_standard": "crmls",
"address": "123 Main St, Los Angeles, CA 90001",
"mls_number": "CL-2026-12345",
},
)
listing = response.json()
listing_id = listing["id"]
print(f"Created listing: {listing_id} (status: {listing['status']})")

Add Photos to a Listing

Photos must already be uploaded. Pass the image UUIDs from the upload step.

python
response = requests.post(
f"https://api.scopix.ai/api/v2/mls/listings/{listing_id}/photos",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"image_ids": ["IMG_1", "IMG_2", "IMG_3"],
},
)
listing = response.json()
print(f"Photo count: {listing['photo_count']}")

Set Photo Order

Provide the full ordered list of image UUIDs. This replaces the current order entirely.

python
response = requests.put(
f"https://api.scopix.ai/api/v2/mls/listings/{listing_id}/photos/order",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"image_ids": ["IMG_3", "IMG_1", "IMG_2"], # New order
},
)

Run Compliance Analysis

Analyze the listing's photos against its MLS standard. The result is persisted as a snapshot.

python
response = requests.post(
f"https://api.scopix.ai/api/v2/mls/listings/{listing_id}/compliance/run",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
snapshot = response.json()
print(f"Quality Score: {snapshot['quality_score']}/100")
print(f"Completeness: {snapshot['completeness_score']}/100")
print(f"Compliant: {snapshot['compliant_photos']}/{snapshot['total_photos']}")
# Full analysis results are in snapshot_data
data = snapshot["snapshot_data"]
for rec in data.get("recommendations", []):
print(f" → {rec}")

Retrieve Compliance Results

Get the latest snapshot or browse the full history.

python
# Latest compliance snapshot
response = requests.get(
f"https://api.scopix.ai/api/v2/mls/listings/{listing_id}/compliance",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
latest = response.json()
# Compliance history (paginated)
response = requests.get(
f"https://api.scopix.ai/api/v2/mls/listings/{listing_id}/compliance/history",
headers={"Authorization": "Bearer YOUR_API_KEY"},
params={"limit": 10, "offset": 0},
)
history = response.json()
print(f"Total snapshots: {history['total']}")
for snap in history["snapshots"]:
print(f" {snap['created_at']}: quality={snap['quality_score']}, completeness={snap['completeness_score']}")

Listing CRUD

You can also list, update, and delete listings. Use GET /mls/listings with optional status and project_id query params to filter. Use PATCH /mls/listings/{id} to update metadata or transition status (active or archived). Use DELETE /mls/listings/{id} to soft-delete.

Understanding Results

Quality Score (1–100)

Each photo receives a weighted quality score based on five dimensions:

DimensionWeight
Lighting — brightness, exposure, shadow balance25%
Composition — framing, camera angle, horizon level25%
Staging — furniture arrangement, cleanliness, décor20%
Clutter — personal items, visual noise15%
Resolution — sharpness, noise, compression artifacts15%

90–100: Professional real estate photographer quality

70–89: Good quality agent photo

50–69: Acceptable but noticeable issues

30–49: Below standard, should be reshot

1–29: Unacceptable for listing use

Compliance Checks

Each rule check returns passed: true/false with a severity of error (must fix) or warning (recommended). Common checks include:

Technical

  • Minimum width (1024px) and height (768px)
  • Maximum file size (10–15MB by standard)
  • File format (JPEG/PNG only)

Content

  • No watermarks or agent branding
  • No identifiable faces
  • No For Sale signs (CRMLS)
  • No people or pets (NWMLS)
  • No sky replacement (CRMLS, Bright MLS)

Remediation

Every failed check comes with a specific, actionable fix message. Examples:

"Resize image to at least 1024px wide. Current: 512px."

"Remove all watermarks from the photo."

"Retake the photo without identifiable people (or pets), or blur faces before uploading."

"Use the original sky. Do not digitally replace or enhance the sky."

"Retake the photo without the For Sale/Sold sign visible, or crop it out."

Completeness Score

Measures what percentage of required photo types are present in the listing. If your standard requires an exterior_front photo and one is missing, the score drops and the missing_photo_types array tells you exactly what to add. The recommendations array provides actionable next steps.