pymlsapi 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. pymlsapi-0.1.0/.github/workflows/publish.yml +29 -0
  2. pymlsapi-0.1.0/.github/workflows/test.yml +31 -0
  3. pymlsapi-0.1.0/.gitignore +38 -0
  4. pymlsapi-0.1.0/PKG-INFO +570 -0
  5. pymlsapi-0.1.0/README.md +540 -0
  6. pymlsapi-0.1.0/SPEC.md +328 -0
  7. pymlsapi-0.1.0/pyproject.toml +73 -0
  8. pymlsapi-0.1.0/src/pymlsapi/__init__.py +103 -0
  9. pymlsapi-0.1.0/src/pymlsapi/async_client.py +67 -0
  10. pymlsapi-0.1.0/src/pymlsapi/async_http.py +104 -0
  11. pymlsapi-0.1.0/src/pymlsapi/client.py +67 -0
  12. pymlsapi-0.1.0/src/pymlsapi/config.py +58 -0
  13. pymlsapi-0.1.0/src/pymlsapi/errors.py +95 -0
  14. pymlsapi-0.1.0/src/pymlsapi/http.py +155 -0
  15. pymlsapi-0.1.0/src/pymlsapi/models/__init__.py +100 -0
  16. pymlsapi-0.1.0/src/pymlsapi/models/common.py +66 -0
  17. pymlsapi-0.1.0/src/pymlsapi/models/content.py +92 -0
  18. pymlsapi-0.1.0/src/pymlsapi/models/intelligence.py +65 -0
  19. pymlsapi-0.1.0/src/pymlsapi/models/listings.py +91 -0
  20. pymlsapi-0.1.0/src/pymlsapi/models/studio.py +171 -0
  21. pymlsapi-0.1.0/src/pymlsapi/poller.py +102 -0
  22. pymlsapi-0.1.0/src/pymlsapi/resources/__init__.py +20 -0
  23. pymlsapi-0.1.0/src/pymlsapi/resources/account/__init__.py +38 -0
  24. pymlsapi-0.1.0/src/pymlsapi/resources/account/billing.py +74 -0
  25. pymlsapi-0.1.0/src/pymlsapi/resources/account/keys.py +46 -0
  26. pymlsapi-0.1.0/src/pymlsapi/resources/content.py +77 -0
  27. pymlsapi-0.1.0/src/pymlsapi/resources/intelligence.py +47 -0
  28. pymlsapi-0.1.0/src/pymlsapi/resources/listings.py +179 -0
  29. pymlsapi-0.1.0/src/pymlsapi/resources/studio/__init__.py +56 -0
  30. pymlsapi-0.1.0/src/pymlsapi/resources/studio/creatives.py +124 -0
  31. pymlsapi-0.1.0/src/pymlsapi/resources/studio/custom.py +100 -0
  32. pymlsapi-0.1.0/src/pymlsapi/resources/studio/enhance.py +170 -0
  33. pymlsapi-0.1.0/src/pymlsapi/resources/studio/floorplan.py +166 -0
  34. pymlsapi-0.1.0/src/pymlsapi/resources/studio/jobs.py +86 -0
  35. pymlsapi-0.1.0/src/pymlsapi/resources/studio/render.py +96 -0
  36. pymlsapi-0.1.0/src/pymlsapi/resources/studio/social.py +57 -0
  37. pymlsapi-0.1.0/src/pymlsapi/resources/studio/staging.py +694 -0
  38. pymlsapi-0.1.0/src/pymlsapi/resources/studio/upload.py +93 -0
  39. pymlsapi-0.1.0/src/pymlsapi/resources/studio/video.py +346 -0
  40. pymlsapi-0.1.0/tests/conftest.py +6 -0
  41. pymlsapi-0.1.0/tests/test_account.py +68 -0
  42. pymlsapi-0.1.0/tests/test_client.py +53 -0
  43. pymlsapi-0.1.0/tests/test_content.py +73 -0
  44. pymlsapi-0.1.0/tests/test_errors.py +95 -0
  45. pymlsapi-0.1.0/tests/test_intelligence.py +73 -0
  46. pymlsapi-0.1.0/tests/test_listings.py +134 -0
  47. pymlsapi-0.1.0/tests/test_models.py +64 -0
  48. pymlsapi-0.1.0/tests/test_poller.py +81 -0
  49. pymlsapi-0.1.0/tests/test_studio.py +370 -0
  50. pymlsapi-0.1.0/uv.lock +558 -0
@@ -0,0 +1,29 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ pypi-publish:
10
+ name: Build and publish Python 🐍 distribution 📦 to PyPI
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ id-token: write # Mandatory for PyPI Trusted Publishing
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v3
20
+ with:
21
+ version: "latest"
22
+
23
+ - name: Build distributions
24
+ run: uv build
25
+
26
+ - name: Publish to PyPI
27
+ uses: pypa/gh-action-pypi-publish@release/v1
28
+ with:
29
+ packages-dir: dist/
@@ -0,0 +1,31 @@
1
+ name: Test & Lint
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Install uv
20
+ uses: astral-sh/setup-uv@v3
21
+ with:
22
+ version: "latest"
23
+
24
+ - name: Set up Python ${{ matrix.python-version }}
25
+ run: uv python install ${{ matrix.python-version }}
26
+
27
+ - name: Install dependencies & run tests
28
+ run: uv run --python ${{ matrix.python-version }} --extra dev pytest
29
+
30
+ - name: Lint check
31
+ run: uv run --python ${{ matrix.python-version }} --with ruff ruff check src tests
@@ -0,0 +1,38 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.so
5
+ .Python
6
+ build/
7
+ develop-eggs/
8
+ dist/
9
+ downloads/
10
+ eggs/
11
+ .eggs/
12
+ lib/
13
+ lib64/
14
+ parts/
15
+ sdist/
16
+ var/
17
+ wheels/
18
+ share/python-wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ MANIFEST
23
+
24
+ # Virtual environments
25
+ .env
26
+ .venv
27
+ env/
28
+ venv/
29
+ ENV/
30
+ env.bak/
31
+ venv.bak/
32
+
33
+ # Testing
34
+ .pytest_cache/
35
+ .coverage
36
+ htmlcov/
37
+ .mypy_cache/
38
+ .ruff_cache/
@@ -0,0 +1,570 @@
1
+ Metadata-Version: 2.5
2
+ Name: pymlsapi
3
+ Version: 0.1.0
4
+ Summary: Official Python client library for mlsapi.dev — Real estate MLS listing ingestion, property intelligence, and Studio visual AI
5
+ Project-URL: Homepage, https://mlsapi.dev
6
+ Project-URL: Documentation, https://docs.mlsapi.dev
7
+ Project-URL: Repository, https://github.com/mlsapi/mlsapi-python
8
+ Project-URL: Changelog, https://github.com/mlsapi/mlsapi-python/releases
9
+ Author-email: MLS API Team <support@mlsapi.dev>
10
+ License-Expression: MIT
11
+ Keywords: 3d-dollhouse,floorplan,generative-ai,mls,property-intelligence,proptech,real-estate,virtual-staging
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.9
23
+ Requires-Dist: httpx>=0.25.0
24
+ Requires-Dist: pydantic>=2.0.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
27
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
28
+ Requires-Dist: respx>=0.21.0; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # mlsapi
32
+
33
+ The official Python client library for **[mlsapi.dev](https://mlsapi.dev)**.
34
+
35
+ Access real-time MLS listing data, property intelligence, CapEx lifecycle analysis, AI-generated marketing copy, and the complete suite of **Studio Visual AI** generative tools (virtual staging, twilight conversion, decluttering, 3D dollhouse floor plans, 4K upscaling, ad creatives, and video generation).
36
+
37
+ [![PyPI version](https://img.shields.io/pypi/v/pymlsapi.svg?style=flat-square)](https://pypi.org/project/pymlsapi/)
38
+ [![Python versions](https://img.shields.io/pypi/pyversions/mlsapi.svg?style=flat-square)](https://pypi.org/project/pymlsapi/)
39
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://opensource.org/licenses/MIT)
40
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square)](https://github.com/psf/black)
41
+
42
+ ---
43
+
44
+ ## Table of Contents
45
+
46
+ - [Features](#features)
47
+ - [Installation](#installation)
48
+ - [Quick Start](#quick-start)
49
+ - [Synchronous Example](#synchronous-example)
50
+ - [Asynchronous (asyncio) Example](#asynchronous-asyncio-example)
51
+ - [Configuration & Authentication](#configuration--authentication)
52
+ - [Core Features & Code Examples](#core-features--code-examples)
53
+ - [1. Real-Time MLS Listing Lookup & Ingestion](#1-real-time-mls-listing-lookup--ingestion)
54
+ - [2. Property Intelligence & CapEx Analysis](#2-property-intelligence--capex-analysis)
55
+ - [3. Marketing Content Generation](#3-marketing-content-generation)
56
+ - [4. Media Upload to Global CDN](#4-media-upload-to-global-cdn)
57
+ - [5. Virtual Room Staging (29 Architectural Styles)](#5-virtual-room-staging-29-architectural-styles)
58
+ - [6. Day-to-Dusk Twilight & Exterior Enhancement](#6-day-to-dusk-twilight--exterior-enhancement)
59
+ - [7. Declutter & Clean Space](#7-declutter--clean-space)
60
+ - [8. De-Staging (Empty Room) & Floor Restoration](#8-de-staging-empty-room--floor-restoration)
61
+ - [9. Furniture & Surface Material Replacement](#9-furniture--surface-material-replacement)
62
+ - [10. 3x3 Designer Wall Paint Swatches](#10-3x3-designer-wall-paint-swatches)
63
+ - [11. 2D Blueprint to 3D Isometric Dollhouse](#11-2d-blueprint-to-3d-isometric-dollhouse)
64
+ - [12. 4K Super-Resolution Upscaling](#12-4k-super-resolution-upscaling)
65
+ - [13. Branded Multi-Placement Ad Creatives](#13-branded-multi-placement-ad-creatives)
66
+ - [14. AI Video Walkthroughs & Voice/Subtitle Polish](#14-ai-video-walkthroughs--voicesubtitle-polish)
67
+ - [Asynchronous Jobs & Progress Callbacks](#asynchronous-jobs--progress-callbacks)
68
+ - [Error Handling](#error-handling)
69
+ - [Supported Presets Reference](#supported-presets-reference)
70
+ - [License](#license)
71
+
72
+ ---
73
+
74
+ ## Features
75
+
76
+ - **Dual Sync & Async Interfaces:** Native synchronous `MlsApiClient` and async `AsyncMlsApiClient` for high-throughput `asyncio` applications.
77
+ - **Deep Type Safety:** Pydantic v2 domain models with full IDE autocompletion, type hinting, and runtime validation.
78
+ - **Smart Asynchronous Polling:** Auto-waiting helper methods (`*_and_wait(...)`) with exponential backoff, jitter, and real-time progress callbacks.
79
+ - **Resilient Networking:** Built on `httpx` with automatic connection pooling and smart retries on HTTP 429 rate limits and 5xx server errors.
80
+ - **Complete Studio Coverage:** First-class access to all 21+ Studio generative visual endpoints.
81
+
82
+ ---
83
+
84
+ ## Installation
85
+
86
+ Install via pip, uv, or poetry:
87
+
88
+ ```bash
89
+ # pip
90
+ pip install pymlsapi
91
+
92
+ # uv
93
+ uv add pymlsapi
94
+
95
+ # poetry
96
+ poetry add pymlsapi
97
+ ```
98
+
99
+ Requires **Python 3.9+**.
100
+
101
+ ---
102
+
103
+ ## Quick Start
104
+
105
+ ### Synchronous Example
106
+
107
+ ```python
108
+ import os
109
+ from pymlsapi import MlsApiClient
110
+
111
+ # Initialize the client with your API key
112
+ mls = MlsApiClient(api_key=os.environ.get("MLSAPI_KEY"))
113
+
114
+ # 1. Fetch normalized MLS listing data
115
+ listing = mls.listings.get_and_wait("A12079565")
116
+ print(f"Property: {listing.address.formatted} - ${listing.price:,.2f}")
117
+ print(f"Downloaded {listing.photo_count} photos: {listing.photos[0]}")
118
+
119
+ # 2. Perform AI Virtual Staging on an empty room photo
120
+ staged = mls.studio.staging.stage_and_wait(
121
+ photo_url=listing.photos[0],
122
+ room_type="living_room",
123
+ style="scandinavian",
124
+ custom_staging_instructions="Oak dining table, bouclé accent chairs, fiddle-leaf fig tree",
125
+ )
126
+
127
+ print(f"Staged photo ready: {staged.staged_photo_url}")
128
+ print(f"Before/after comparison: {staged.before_after_comparison_url}")
129
+ ```
130
+
131
+ ### Asynchronous (asyncio) Example
132
+
133
+ ```python
134
+ import asyncio
135
+ import os
136
+ from pymlsapi import AsyncMlsApiClient
137
+
138
+ async def main():
139
+ async with AsyncMlsApiClient(api_key=os.environ.get("MLSAPI_KEY")) as mls:
140
+ # Ingest listing and synthesize intelligence concurrently
141
+ listing_task = mls.listings.get_and_wait("A12079565")
142
+ intel_task = mls.intelligence.get("A12079565", investor_mode=True)
143
+
144
+ listing, intel = await asyncio.gather(listing_task, intel_task)
145
+
146
+ print(f"Listing: {listing.address.city}, {listing.address.state}")
147
+ print(f"Gross Yield: {intel.llm_derived_intelligence.investor_insights.estimated_gross_yield_pct}%")
148
+
149
+ asyncio.run(main())
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Configuration & Authentication
155
+
156
+ Obtain your API key from the **[mlsapi.dev Dashboard](https://mlsapi.dev)**.
157
+
158
+ ```python
159
+ from pymlsapi import MlsApiClient
160
+
161
+ mls = MlsApiClient(
162
+ api_key="sk_live_...", # Secret API key (or MLSAPI_KEY env var)
163
+ environment="live", # "live" (production) or "test" (sandbox)
164
+ base_url="https://api.mlsapi.dev", # Optional custom base URL or staging endpoint
165
+ timeout_seconds=60.0, # HTTP request timeout (default: 60s)
166
+ max_retries=3, # Automatic retries on rate limits (429) & 5xx errors
167
+ )
168
+ ```
169
+
170
+ ---
171
+
172
+ ## Core Features & Code Examples
173
+
174
+ ### 1. Real-Time MLS Listing Lookup & Ingestion
175
+
176
+ Ingest property records by MLS number. If the property is not cached, the engine enqueues live scraping and photo downloading.
177
+
178
+ ```python
179
+ # Auto-wait until scraping completes (recommended)
180
+ listing = mls.listings.get_and_wait(
181
+ "A12079565",
182
+ timeout_seconds=45.0,
183
+ on_progress=lambda job: print(f"Ingestion step: {job.step}"),
184
+ )
185
+
186
+ print(listing.address.city, listing.specifications.beds, listing.specifications.baths_full)
187
+ print(f"Downloaded {listing.photo_count} high-res photos: {listing.photos}")
188
+
189
+ # Or handle the asynchronous job tracker manually
190
+ response = mls.listings.get("A12079565")
191
+ if hasattr(response, "status") and response.status == "processing":
192
+ print(f"Ingestion job queued with tracker ID: {response.job_id}")
193
+ ```
194
+
195
+ ---
196
+
197
+ ### 2. Property Intelligence & CapEx Analysis
198
+
199
+ Synthesize public tax records, historical ownership, school zoning, replacement horizons for major structural systems (roof, HVAC, water heater, impact windows), and investor yields.
200
+
201
+ ```python
202
+ intel = mls.intelligence.get(
203
+ "A12079565",
204
+ include_llm=True, # Deep AI analysis of remarks and conditions
205
+ investor_mode=True, # Include estimated rent, gross yield, and HOA flags
206
+ )
207
+
208
+ insights = intel.llm_derived_intelligence.investor_insights
209
+ capex = intel.llm_derived_intelligence.systems_and_capex
210
+
211
+ print(f"Estimated Monthly Rent: ${insights.estimated_monthly_rent.median:,.2f}")
212
+ print(f"Gross Yield: {insights.estimated_gross_yield_pct}%")
213
+ print(f"Roof Age & Condition: {capex.roof.age_years} years - {capex.roof.condition}")
214
+ print(f"Impact windows detected: {capex.storm_protection.has_impact_windows}")
215
+ ```
216
+
217
+ ---
218
+
219
+ ### 3. Marketing Content Generation
220
+
221
+ Generate multi-channel marketing campaigns tailored by tone, target audience, and channel format.
222
+
223
+ ```python
224
+ copy = mls.content.generate(
225
+ "A12079565",
226
+ outputs=["social", "email_blast", "video_script", "flyer_bullets", "mls_remarks"],
227
+ social_platforms=["instagram", "linkedin", "facebook", "tiktok"],
228
+ tone="luxury",
229
+ target_audience="High-net-worth buyers relocating to South Florida",
230
+ )
231
+
232
+ # Access typed content
233
+ print("Instagram Caption:\n", copy.content.social.instagram.caption)
234
+ print("Instagram Hashtags:\n", copy.content.social.instagram.hashtags)
235
+ print("Video Script Hook:\n", copy.content.video_script.hook)
236
+ print("Optimized MLS Remarks:\n", copy.content.mls_remarks)
237
+ ```
238
+
239
+ ---
240
+
241
+ ### 4. Media Upload to Global CDN
242
+
243
+ Upload local image files, binary bytes, or open file objects directly to the `mlsapi.dev` CDN to use as inputs for any Studio operation.
244
+
245
+ ```python
246
+ from pathlib import Path
247
+
248
+ # 1. Upload from a local filesystem path
249
+ upload1 = mls.studio.upload(Path("./photos/vacant_living_room.jpg"))
250
+ print("CDN URL:", upload1.url)
251
+
252
+ # 2. Upload from raw bytes
253
+ with open("./photos/blueprint.png", "rb") as f:
254
+ upload2 = mls.studio.upload(
255
+ f.read(),
256
+ filename="blueprint.png",
257
+ content_type="image/png",
258
+ )
259
+ print("Uploaded blueprint:", upload2.url)
260
+ ```
261
+
262
+ ---
263
+
264
+ ### 5. Virtual Room Staging (29 Architectural Styles)
265
+
266
+ Furnish vacant room photos with photorealistic staging adhering to real estate staging standards.
267
+
268
+ ```python
269
+ staged = mls.studio.staging.stage_and_wait(
270
+ photo_url="https://cdn.mlsapi.dev/uploads/vacant_living_room.jpg",
271
+ room_type="living_room",
272
+ style="luxury", # Choose from 29 styles (e.g. 'modern', 'japandi', 'coastal')
273
+ preserve_flooring=True, # Keep original hardwood/tile flooring
274
+ custom_staging_instructions="White boucle sectional, travertine coffee table, minimalist wall art",
275
+ )
276
+
277
+ print("Staged image:", staged.staged_photo_url)
278
+ print("Before/after slider:", staged.before_after_comparison_url)
279
+ print("Staging manifest:", staged.staging_manifest)
280
+ ```
281
+
282
+ ---
283
+
284
+ ### 6. Day-to-Dusk Twilight & Exterior Enhancement
285
+
286
+ Transform daytime exterior photos into dramatic golden-hour twilight scenes with warm interior illumination, or enhance sunny curb appeal.
287
+
288
+ ```python
289
+ # 1. Twilight Day-to-Dusk conversion
290
+ twilight = mls.studio.staging.twilight_and_wait(
291
+ photo_url="https://cdn.mlsapi.dev/uploads/exterior_day.jpg",
292
+ mode="day_to_dusk", # Or 'blue_sky_replace'
293
+ )
294
+ print("Twilight exterior:", twilight.enhanced_photo_url)
295
+
296
+ # 2. Exterior enhancements (blue sky, green lawn, pool cleaning)
297
+ enhanced = mls.studio.enhance.exterior_and_wait(
298
+ photo_url="https://cdn.mlsapi.dev/uploads/exterior_overcast.jpg",
299
+ enhancements=["blue_sky", "green_grass", "clean_pool", "tidy_garden"],
300
+ )
301
+ print("Enhanced curb appeal:", enhanced.enhanced_photo_url)
302
+ ```
303
+
304
+ ---
305
+
306
+ ### 7. Declutter & Clean Space
307
+
308
+ Remove tenant clutter, wires, boxes, children's toys, and moving messes while strictly keeping walls, floors, and primary structural architecture intact.
309
+
310
+ ```python
311
+ clean = mls.studio.staging.declutter_and_wait(
312
+ photo_url="https://cdn.mlsapi.dev/uploads/cluttered_kitchen.jpg",
313
+ room_type="kitchen",
314
+ removal_targets=["dishes", "refrigerator magnets", "trash cans", "countertop appliances"],
315
+ )
316
+
317
+ print("Clean photo:", clean.decluttered_photo_url)
318
+ print("Items removed:", clean.items_removed)
319
+ ```
320
+
321
+ ---
322
+
323
+ ### 8. De-Staging (Empty Room) & Floor Restoration
324
+
325
+ Strip out outdated furniture to present prospective buyers with a clean architectural canvas, with optional floor restoration.
326
+
327
+ ```python
328
+ emptied = mls.studio.staging.empty_and_wait(
329
+ photo_url="https://cdn.mlsapi.dev/uploads/dated_bedroom.jpg",
330
+ room_type="bedroom",
331
+ restore_flooring="hardwood", # 'hardwood' | 'tile' | 'carpet' | 'polished_concrete'
332
+ )
333
+
334
+ print("Empty room canvas:", emptied.empty_photo_url)
335
+ ```
336
+
337
+ ---
338
+
339
+ ### 9. Furniture & Surface Material Replacement
340
+
341
+ Replace outdated furniture items with modern pieces or resurface materials like kitchen countertops and flooring.
342
+
343
+ ```python
344
+ # 1. Precision furniture swap
345
+ new_sofa = mls.studio.staging.replace_furniture_and_wait(
346
+ room_photo_url="https://cdn.mlsapi.dev/uploads/living.jpg",
347
+ target_furniture="sofa",
348
+ product_description="Low-profile minimalist Italian cream leather sofa",
349
+ # Or pass an exact product catalog photo:
350
+ # reference_product_image_url="https://example.com/catalog-sofa.jpg",
351
+ )
352
+ print("Updated sofa photo:", new_sofa.result_photo_url)
353
+
354
+ # 2. Surface material replacement
355
+ new_kitchen = mls.studio.staging.replace_material_and_wait(
356
+ room_photo_url="https://cdn.mlsapi.dev/uploads/kitchen.jpg",
357
+ surface_type="countertops",
358
+ material_preset="Calacatta Gold Italian Marble with subtle grey and gold veining",
359
+ )
360
+ print("Updated kitchen countertops:", new_kitchen.result_photo_url)
361
+ ```
362
+
363
+ ---
364
+
365
+ ### 10. 3x3 Designer Wall Paint Swatches
366
+
367
+ Test curated designer paint colors on room walls with an instant 3x3 comparison grid.
368
+
369
+ ```python
370
+ swatches = mls.studio.staging.wall_colors_and_wait(
371
+ photo_url="https://cdn.mlsapi.dev/uploads/living_room.jpg",
372
+ palette_preset="popular_neutrals", # 'popular_neutrals' | 'modern_earth' | 'coastal_breeze' | 'moody_darks'
373
+ )
374
+
375
+ print("3x3 comparison grid:", swatches.comparison_grid_3x3_url)
376
+ for swatch in swatches.swatch_results:
377
+ print(f"Color: {swatch.color_name} ({swatch.hex}) -> {swatch.image_url}")
378
+ ```
379
+
380
+ ---
381
+
382
+ ### 11. 2D Blueprint to 3D Isometric Dollhouse
383
+
384
+ Convert 2D floor plans, architectural blueprints, or hand sketches into 3D isometric cutaway dollhouse renders.
385
+
386
+ ```python
387
+ # Step 1: Analyze floor plan structural geometry
388
+ analysis = mls.studio.floorplan.analyze(
389
+ floorplan_image_url="https://cdn.mlsapi.dev/uploads/floorplan.png",
390
+ style="modern",
391
+ )
392
+ print(f"Rooms detected: {analysis.spatial_summary.total_rooms_detected}")
393
+
394
+ # Step 2: Render 3D isometric dollhouse view
395
+ dollhouse = mls.studio.floorplan.render_3d_and_wait(
396
+ floorplan_image_url="https://cdn.mlsapi.dev/uploads/floorplan.png",
397
+ style="modern",
398
+ include_room_closeups=True,
399
+ )
400
+
401
+ print("3D Dollhouse Render:", dollhouse.isometric_3d_dollhouse_url)
402
+ for closeup in dollhouse.room_renders:
403
+ print(f"Room {closeup.room_name}: {closeup.image_url}")
404
+ ```
405
+
406
+ ---
407
+
408
+ ### 12. 4K Super-Resolution Upscaling
409
+
410
+ Upscale low-resolution or compressed MLS photos up to 4K resolution with AI detail reconstruction.
411
+
412
+ ```python
413
+ upscaled = mls.studio.enhance.upscale_and_wait(
414
+ image_url="https://cdn.mlsapi.dev/uploads/lowres_photo.jpg",
415
+ scale_factor=4, # 2 or 4
416
+ enhance_details=True,
417
+ )
418
+
419
+ print("4K Upscaled image:", upscaled.upscaled_image_url)
420
+ print("Target resolution:", upscaled.target_resolution)
421
+ ```
422
+
423
+ ---
424
+
425
+ ### 13. Branded Multi-Placement Ad Creatives
426
+
427
+ Generate compliant real estate ad creatives with agent branding kits, MLS property badges, and typography across all social and print dimensions.
428
+
429
+ ```python
430
+ ads = mls.studio.creatives.generate_and_wait(
431
+ mls_id="A12079565",
432
+ trigger="just_listed", # 'just_listed' | 'open_house' | 'price_improved' | 'just_sold'
433
+ direction="magazine", # 'magazine' | 'bold' | 'warm'
434
+ placements=["feed_portrait", "square", "link", "flyer"],
435
+ brand_kit={
436
+ "agent_name": "Sarah Connor",
437
+ "brokerage_name": "Compass Beverly Hills",
438
+ "phone": "(310) 555-0199",
439
+ "primary_brand_color": "#0F172A",
440
+ "agent_headshot_url": "https://cdn.example.com/sarah-headshot.jpg",
441
+ },
442
+ )
443
+
444
+ print("1:1 Square Feed Ad:", ads.creatives.get("square").image_url)
445
+ print("9:16 Vertical Story Ad:", ads.creatives.get("feed_portrait").image_url)
446
+ print("Fair Housing compliance passed:", ads.compliance.fair_housing_passed)
447
+ ```
448
+
449
+ ---
450
+
451
+ ### 14. AI Video Walkthroughs & Voice/Subtitle Polish
452
+
453
+ Polish realtor walkthrough videos with studio voice leveling, Hormozi-style animated captions, and automatic vertical 9:16 re-framing.
454
+
455
+ ```python
456
+ polished_video = mls.studio.video.enhance_and_wait(
457
+ video_url="https://cdn.mlsapi.dev/uploads/raw_walkthrough.mp4",
458
+ features={
459
+ "studio_voice": True, # Wind/echo cleanup & voice mastering
460
+ "animated_subtitles": True, # Word-by-word dynamic animated subtitles
461
+ "smart_reframe": True, # Auto-track agent and reframe to 9:16
462
+ },
463
+ subtitle_style={
464
+ "font_theme": "hormozi_bold",
465
+ "primary_color": "#FFFFFF",
466
+ "highlight_color": "#FFDE59",
467
+ },
468
+ export_aspect_ratios=["9:16", "16:9"],
469
+ )
470
+
471
+ print("Reels / TikTok Video:", polished_video.mastered_videos[0].url)
472
+ ```
473
+
474
+ ---
475
+
476
+ ## Asynchronous Jobs & Progress Callbacks
477
+
478
+ Every Studio operation returns immediately with an HTTP 202 `StudioJob` when using the standard method (e.g. `stage(...)`), or polls until completion when using the `*_and_wait(...)` companion method.
479
+
480
+ ### Custom Polling Options & Progress Hook
481
+
482
+ ```python
483
+ def on_progress(job):
484
+ print(f"[{job.progress_percentage}%] Step: {job.current_step}")
485
+
486
+ result = mls.studio.staging.stage_and_wait(
487
+ photo_url="https://cdn.mlsapi.dev/uploads/room.jpg",
488
+ style="japandi",
489
+ poll_interval=2.0, # Poll every 2.0 seconds (default: 2.0s)
490
+ timeout_seconds=120.0, # Maximum wait time (default: 90.0s)
491
+ on_progress=on_progress, # Optional progress callback
492
+ )
493
+ ```
494
+
495
+ ### Manual Job Tracking
496
+
497
+ ```python
498
+ # Dispatch without waiting
499
+ job = mls.studio.staging.stage(photo_url="https://cdn.mlsapi.dev/uploads/room.jpg")
500
+ print(f"Track job later: {job.job_id}")
501
+
502
+ # Check status later
503
+ current_status = mls.studio.jobs.get(job.job_id)
504
+ print(f"Status: {current_status.status}, progress: {current_status.progress_percentage}%")
505
+
506
+ # Or wait for it when ready
507
+ completed_job = mls.studio.jobs.wait_for(job.job_id, timeout_seconds=90.0)
508
+ print("Result URL:", completed_job.result.staged_photo_url)
509
+ ```
510
+
511
+ ---
512
+
513
+ ## Error Handling
514
+
515
+ All API errors inherit from `MlsApiError` and expose the HTTP status code, error code, and server message.
516
+
517
+ ```python
518
+ from pymlsapi.errors import (
519
+ MlsApiError,
520
+ AuthenticationError,
521
+ NotFoundError,
522
+ RateLimitError,
523
+ InsufficientCreditsError,
524
+ JobTimeoutError,
525
+ )
526
+
527
+ try:
528
+ listing = mls.listings.get_and_wait("INVALID_ID")
529
+ except AuthenticationError as e:
530
+ print("Invalid API Key:", e.message)
531
+ except NotFoundError as e:
532
+ print("Listing or resource not found:", e.message)
533
+ except RateLimitError as e:
534
+ print(f"Rate limited. Quota resets in {e.retry_after_seconds}s")
535
+ except InsufficientCreditsError as e:
536
+ print("Insufficient credits in workspace balance. Top up at https://mlsapi.dev/billing")
537
+ except JobTimeoutError as e:
538
+ print(f"Job polling timed out after {e.timeout_seconds}s")
539
+ except MlsApiError as e:
540
+ print(f"API Error [{e.code}]: {e.message}")
541
+ ```
542
+
543
+ ---
544
+
545
+ ## Supported Presets Reference
546
+
547
+ ### Interior Design Styles (29 Presets)
548
+
549
+ | | | |
550
+ |---|---|---|
551
+ | `modern` | `luxury` | `scandinavian` |
552
+ | `japandi` | `industrial` | `bohemian` |
553
+ | `minimalist` | `coastal` | `mid_century_modern` |
554
+ | `art_deco` | `farmhouse` | `mediterranean` |
555
+ | `contemporary` | `rustic` | `transitional` |
556
+ | `french_country` | `hollywood_regency` | `eclectic` |
557
+ | `zen` | `bauhaus` | `victorian` |
558
+ | `tropical` | `modern_craftsman` | `southwestern` |
559
+ | `wabi_sabi` | `shabby_chic` | `chalet` |
560
+ | `urban_loft` | `custom` | |
561
+
562
+ ### Architectural Room Types (12 Types)
563
+
564
+ `living_room`, `bedroom`, `primary_bedroom`, `dining_room`, `kitchen`, `bathroom`, `patio`, `outdoor_patio`, `home_office`, `entryway`, `basement`, `commercial_lobby`.
565
+
566
+ ---
567
+
568
+ ## License
569
+
570
+ MIT © [mlsapi.dev](https://mlsapi.dev)