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.
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.
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.
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.
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
{ "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
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 MLSprint("\nRecommended Order:")for photo in analysis["ordered_photos"]: print(f" {photo['image_context']}: {photo['image_id']} (quality: {photo['quality_score']})")
# Missing photo typesif analysis["missing_photo_types"]: print(f"\nMissing: {', '.join(analysis['missing_photo_types'])}")
# Actionable recommendationsfor 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
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.
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.
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.
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_datadata = snapshot["snapshot_data"]for rec in data.get("recommendations", []): print(f" → {rec}")Retrieve Compliance Results
Get the latest snapshot or browse the full history.
# Latest compliance snapshotresponse = 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:
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.

