{"openapi":"3.1.0","info":{"title":"Website Property API","description":"Review draft for Feature 110. Anonymous website-consumer operations only. Deployment and host availability are unverified. The placeholder server is intentionally non-routable. Try It is disabled; do not substitute a production host. Normal public responses and handled public errors use Cache-Control: no-store; generic unhandled 500 responses may omit it. Optional response properties can be omitted; explicit null is retained when the projection supplies it.","version":"1.0.0-draft"},"paths":{"/api/v1/public/properties/search":{"post":{"summary":"Search properties","operationId":"search_api_v1_public_properties_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyWebsiteSearchRequest"},"examples":{"minimalSale":{"summary":"Sale — bounds and operation","value":{"destination":"TENERIFE","area":{"kind":"BOUNDS","south":28,"west":-16.9,"north":28.6,"east":-16.1},"filters":{"operation":"SALES"},"page":1,"page_size":24}},"allSaleFilters":{"summary":"Sale — all applicable filter fields","value":{"destination":"TENERIFE","area":{"kind":"BOUNDS","south":28,"west":-16.9,"north":28.6,"east":-16.1},"filters":{"operation":"SALES","city":"Adeje","area":"Example area","complex_name":"Example complex","ubicacion":["example-local-area"],"property_type":["HOMES"],"features_type":["FLAT"],"property_detail_type":["PENTHOUSE_DUPLEX"],"catalogs":["example-sale-collection"],"bedrooms":{"min":2,"max":4},"bathrooms":{"min":1,"max":3},"total_area_m2":{"min":80,"max":150},"price":{"min":"300000.00","max":"500000.00"},"is_new_construction":false,"has_terrace":true,"has_pool":true,"has_parking":true,"has_lift":true,"sea_view":true,"view_types":["SEA"],"updated_at":{"from":"2026-01-01T00:00:00Z","to":"2026-12-31T23:59:59Z"}},"page":1,"page_size":24,"sort":"PUBLIC_ID_ASC"}},"rentalContext":{"summary":"Rental type and rental price range","value":{"destination":"TENERIFE","area":{"kind":"BOUNDS","south":28,"west":-16.9,"north":28.6,"east":-16.1},"filters":{"operation":"RENTAL","rental_type":"LONG_TERM","price":{"min":"1000.00","max":"2500.00"}},"page":1,"page_size":24}},"polygonSale":{"summary":"Sale — polygon instead of bounds","value":{"destination":"TENERIFE","area":{"kind":"POLYGON","vertices":[{"lat":28,"lng":-16.9},{"lat":28.6,"lng":-16.9},{"lat":28.6,"lng":-16.1},{"lat":28,"lng":-16.1}]},"filters":{"operation":"SALES"},"page":1,"page_size":24}}}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyWebsiteSearchResponse"},"examples":{"populatedSale":{"summary":"Sale — every public summary field populated","value":{"items":[{"public_id":"P9001","name":"Example coastal penthouse duplex","operation":"SALES","price":{"amount":"425000.00","currency":"EUR","kind":"SALE","period":"ONE_OFF"},"asking_price_per_m2":"4250.00","property_type":"HOMES","features_type":"FLAT","property_detail_type":"PENTHOUSE_DUPLEX","bedrooms":3,"bathrooms":2,"total_area_m2":100,"city":"Adeje","region":"Santa Cruz de Tenerife","ubicacion":{"key":"example-local-area","label":"Example local area","city":"Adeje"},"view_types":["SEA","MOUNTAIN"],"catalogs":["example-sale-collection"],"location_facts":{"altitude_m":120,"climate_zone":"TENERIFE_SOUTH","distance_to_sea_m":900,"distance_to_airport_km":20,"distance_to_nearest_school_km":1.2,"distance_to_nearest_healthcare_km":2.4,"short_term_rental_possible":false},"location":{"lat":28.1,"lng":-16.7,"precision":"EXACT"},"thumbnail":{"asset_id":"00000000-0000-4000-8000-000000009001","url":"/api/v1/public/properties/P9001/images/00000000-0000-4000-8000-000000009001","caption":"TERRACE"}}],"total":1,"page":1,"page_size":24,"total_pages":1}},"emptyPage":{"summary":"No matching properties","value":{"items":[],"total":0,"page":1,"page_size":24,"total_pages":0}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"404":{"description":"Public API/media disabled, or eligible listing/profile/asset unavailable. Messages may be 'Not Found' or 'Not found'.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Not Found"}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"413":{"description":"Public search request body too large. Source default maximum is 65,536 bytes, enforced on the streamed body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Illustrative sanitized error message"}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"422":{"description":"Invalid request, filter selection, UUID, geometry, range or unavailable operation context. Request-validation errors are capped at 20 items; locations at 8 parts; text parts/type at 80 and message at 160 characters. Service validation uses the same loc/type/msg shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicValidationError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":[{"loc":["body","filters","operation"],"type":"literal_error","msg":"Illustrative sanitized validation message"}]}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"429":{"description":"Public request limit exceeded. Honor Retry-After before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Illustrative sanitized error message"}}}}},"headers":{"Retry-After":{"description":"Seconds until retry; always present on 429, present on limiter-origin 503 only.","schema":{"type":"string","pattern":"^[1-9][0-9]*$"}},"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"500":{"description":"An unhandled application error becomes the generic JSON detail 'Internal Server Error'. This outer exception response may omit Cache-Control: no-store.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Internal Server Error"}}}}}},"503":{"description":"Temporary public limiter, database or projection failure. Limiter failures include Retry-After: 1; other service failures may omit it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Illustrative sanitized error message"}}}}},"headers":{"Retry-After":{"description":"Seconds until retry; always present on 429, present on limiter-origin 503 only.","schema":{"type":"string","pattern":"^[1-9][0-9]*$"}},"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}}},"tags":["Search"],"description":"Anonymous search in required bounds or polygon, with operation-scoped filters. PUBLIC_ID_ASC is the only accepted sort literal; implementation orders by numeric canonical reference ascending with an internal tie-breaker. This is not lexicographic public_id sorting. Totals use the same filters. All examples are synthetic public-wire fixtures, not live listings. Optional fields are populated to demonstrate schema coverage; real responses may omit them. Catalog/LocalArea keys, labels, climate colors, phones, assets and addresses in examples are illustrative, not an active registry. Fetch reference data before using registry-backed filter values. The full SALES request demonstrates every sale-relevant filter; remove filters the visitor has not selected. rental_type is a RENTAL-only context example here. Request area/complex_name are not returned property fields.","security":[],"x-readme":{"explorer-enabled":false},"x-explorer-enabled":false}},"/api/v1/public/property-reference":{"get":{"summary":"Get website reference data","operationId":"reference_api_v1_public_property_reference_get","parameters":[{"name":"destination","in":"query","required":false,"schema":{"const":"TENERIFE","type":"string","default":"TENERIFE","title":"Destination"},"example":"TENERIFE"},{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"City"},"example":"Adeje"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPropertyReference"},"examples":{"withCity":{"summary":"All reference fields, including local_areas with city query","value":{"schema_version":"2026-10-19.1","destination":{"key":"TENERIFE","extent":{"south":27.9,"west":-17,"north":28.7,"east":-16,"version":1}},"operations":["SALES","RENTAL"],"rental_types":["TEMPORAL","LONG_TERM","SHORT_TERM"],"view_types":["SEA","GARDEN","MOUNTAIN","STREET","NEIGHBORHOOD","POOL","SEA_AND_COAST","PANORAMIC_SEA","PANORAMIC_SEA_AND_ISLANDS","MOUNTAIN_AND_SEA","POOL_AND_GARDEN","STREET_AND_MOUNTAIN"],"property_types":["HOMES","GARAGE","OFFICE","PREMISES_COMMERCIAL","LAND","STORAGE","BUILDING"],"features_types":["FLAT","HOUSE","HOUSE_INDEPENDENT","HOUSE_SEMIDETACHED","HOUSE_TERRACED","RUSTIC","GARAGE","OFFICE","PREMISES","PREMISES_COMMERCIAL","PREMISES_INDUSTRIAL","LAND","LAND_URBAN","LAND_COUNTRYBUILDABLE","LAND_COUNTRYNONBUILDABLE","STORAGE","BUILDING_HOTEL","BUILDING_COMMERCIAL","BUILDING_INDUSTRIAL","BUILDING_OFFICE","BUILDING_CHALET","BUILDING_OTHER"],"property_detail_types":["DUPLEX","PENTHOUSE","PENTHOUSE_DUPLEX","STUDIO","BUNGALOW","CORNER"],"climate_zones":[{"value":"NORTHERN_TENERIFE","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"NORTH_EAST_SANTA_CRUZ","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"EASTERN_COAST","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"TENERIFE_SOUTH","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"HIGH_MOUNTAINS","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"LA_LAGUNA_LA_OROTAVA","labels":{"en":"Example climate label"},"color":"#4472d0"}],"catalogs":[{"key":"example-sale-collection","parent_key":null,"labels":{"en":"Example sale collection","es":"Colección de ejemplo"},"sort_order":10}],"local_areas":[{"key":"example-local-area","label":"Example local area","city":"Adeje"}]}},"withoutCity":{"summary":"No city query — local_areas omitted","value":{"schema_version":"2026-10-19.1","destination":{"key":"TENERIFE","extent":{"south":27.9,"west":-17,"north":28.7,"east":-16,"version":1}},"operations":["SALES","RENTAL"],"rental_types":["TEMPORAL","LONG_TERM","SHORT_TERM"],"view_types":["SEA","GARDEN","MOUNTAIN","STREET","NEIGHBORHOOD","POOL","SEA_AND_COAST","PANORAMIC_SEA","PANORAMIC_SEA_AND_ISLANDS","MOUNTAIN_AND_SEA","POOL_AND_GARDEN","STREET_AND_MOUNTAIN"],"property_types":["HOMES","GARAGE","OFFICE","PREMISES_COMMERCIAL","LAND","STORAGE","BUILDING"],"features_types":["FLAT","HOUSE","HOUSE_INDEPENDENT","HOUSE_SEMIDETACHED","HOUSE_TERRACED","RUSTIC","GARAGE","OFFICE","PREMISES","PREMISES_COMMERCIAL","PREMISES_INDUSTRIAL","LAND","LAND_URBAN","LAND_COUNTRYBUILDABLE","LAND_COUNTRYNONBUILDABLE","STORAGE","BUILDING_HOTEL","BUILDING_COMMERCIAL","BUILDING_INDUSTRIAL","BUILDING_OFFICE","BUILDING_CHALET","BUILDING_OTHER"],"property_detail_types":["DUPLEX","PENTHOUSE","PENTHOUSE_DUPLEX","STUDIO","BUNGALOW","CORNER"],"climate_zones":[{"value":"NORTHERN_TENERIFE","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"NORTH_EAST_SANTA_CRUZ","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"EASTERN_COAST","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"TENERIFE_SOUTH","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"HIGH_MOUNTAINS","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"LA_LAGUNA_LA_OROTAVA","labels":{"en":"Example climate label"},"color":"#4472d0"}],"catalogs":[{"key":"example-sale-collection","parent_key":null,"labels":{"en":"Example sale collection","es":"Colección de ejemplo"},"sort_order":10}]}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"404":{"description":"Public API/media disabled, or eligible listing/profile/asset unavailable. Messages may be 'Not Found' or 'Not found'.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Not Found"}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"422":{"description":"Invalid request, filter selection, UUID, geometry, range or unavailable operation context. Request-validation errors are capped at 20 items; locations at 8 parts; text parts/type at 80 and message at 160 characters. Service validation uses the same loc/type/msg shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicValidationError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":[{"loc":["query","destination"],"type":"literal_error","msg":"Illustrative sanitized validation message"}]}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"429":{"description":"Public request limit exceeded. Honor Retry-After before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Illustrative sanitized error message"}}}}},"headers":{"Retry-After":{"description":"Seconds until retry; always present on 429, present on limiter-origin 503 only.","schema":{"type":"string","pattern":"^[1-9][0-9]*$"}},"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"500":{"description":"An unhandled application error becomes the generic JSON detail 'Internal Server Error'. This outer exception response may omit Cache-Control: no-store.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Internal Server Error"}}}}}},"503":{"description":"Temporary public limiter, database or projection failure. Limiter failures include Retry-After: 1; other service failures may omit it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Illustrative sanitized error message"}}}}},"headers":{"Retry-After":{"description":"Seconds until retry; always present on 429, present on limiter-origin 503 only.","schema":{"type":"string","pattern":"^[1-9][0-9]*$"}},"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}}},"tags":["Reference"],"description":"Return current controlled values, catalog labels and destination extent. local_areas is omitted without a city query, included when city is supplied, and [] for a blank city. No municipality list endpoint exists. All examples are synthetic public-wire fixtures, not live listings. Optional fields are populated to demonstrate schema coverage; real responses may omit them. Catalog/LocalArea keys, labels, climate colors, phones, assets and addresses in examples are illustrative, not an active registry. Fetch reference data before using registry-backed filter values. Complete example request: GET /api/v1/public/property-reference?city=Adeje. Examples include all enum values; illustrative climate labels/colors and registry records are not canonical. Never hard-code example registry keys.","security":[],"x-readme":{"explorer-enabled":false},"x-explorer-enabled":false}},"/api/v1/public/properties/{public_id}":{"get":{"summary":"Get property detail","operationId":"detail_api_v1_public_properties__public_id__get","parameters":[{"name":"public_id","in":"path","required":true,"schema":{"type":"string","title":"Public Id"},"example":"P9001"},{"name":"operation","in":"query","required":false,"schema":{"anyOf":[{"enum":["SALES","RENTAL"],"type":"string"},{"type":"null"}],"title":"Operation"},"example":"SALES"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyWebsiteDetail"},"examples":{"completeSale":{"summary":"Sale — every public detail field populated","value":{"public_id":"P9001","name":"Example coastal penthouse duplex","operation":"SALES","operations":["SALES"],"prices":[{"amount":"425000.00","currency":"EUR","kind":"SALE","period":"ONE_OFF","operation":"SALES"}],"price":{"amount":"425000.00","currency":"EUR","kind":"SALE","period":"ONE_OFF"},"asking_price_per_m2":"4250.00","property_type":"HOMES","features_type":"FLAT","property_detail_type":"PENTHOUSE_DUPLEX","bedrooms":3,"bathrooms":2,"total_area_m2":100,"city":"Adeje","region":"Santa Cruz de Tenerife","ubicacion":{"key":"example-local-area","label":"Example local area","city":"Adeje"},"view_types":["SEA","MOUNTAIN"],"catalogs":["example-sale-collection"],"location_facts":{"altitude_m":120,"climate_zone":"TENERIFE_SOUTH","distance_to_sea_m":900,"distance_to_airport_km":20,"distance_to_nearest_school_km":1.2,"distance_to_nearest_healthcare_km":2.4,"short_term_rental_possible":false},"location":{"lat":28.1,"lng":-16.7,"precision":"EXACT"},"description":"Invented sale listing for frontend layout and API mocks.","description_translations":{"en":"Invented sale listing for frontend layout and API mocks.","es":"Anuncio ficticio para ejemplos de interfaz."},"characteristics":{"floor":"3","toilets":1,"living_area_m2":85,"outdoor_area_m2":15,"terrace_area_m2":15,"pool_area_m2":40,"garden_area_m2":60,"built_year":2010,"features_conservation":"GOOD","pool_type":"PUBLIC_HEATED","parking_type":"PARKING_SPACE","parking_spaces":1,"garden_type":"COMMUNAL","kitchen_type":"AMERICAN","furnishing_status":"PARTIALLY_FURNISHED","terrace_glazing":"NOT_GLAZED","window_features":["ALUMINUM","BLINDS"],"is_renovated":true,"last_renovated_year":2024,"is_new_construction":false,"has_terrace":true,"has_garden":true,"has_air_conditioning":true,"has_storage":true,"has_lift":true,"has_wardrobes":true,"has_terrace_awning":true,"has_jacuzzi":false,"has_security_door":true,"has_double_glazing":true,"has_alarm":false,"has_fireplace":false,"has_laundry_room":true,"has_solarium":true,"has_home_cinema":false},"gallery":[{"asset_id":"00000000-0000-4000-8000-000000009001","url":"/api/v1/public/properties/P9001/images/00000000-0000-4000-8000-000000009001","caption":"TERRACE","is_primary":true,"display_order":0}],"agent":{"display_name":"Example Agent","photo_url":"/api/v1/public/agent-images/00000000-0000-4000-8000-000000009002","public_phone":"+12025550101","public_email":"agent@example.invalid","whatsapp_phone":"+12025550101","preferred_contact_method":"EMAIL","preferred_contact_time":"Weekdays, 10:00–16:00 Atlantic/Canary"},"address_line":"Example Street 1 (fictional address)"}},"sparseSale":{"summary":"Sale — optional data absent, no media or agent","value":{"public_id":"P9002","operation":"SALES","operations":["SALES"],"prices":[],"view_types":[],"catalogs":[],"characteristics":{},"gallery":[]}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"404":{"description":"Public API/media disabled, or eligible listing/profile/asset unavailable. Messages may be 'Not Found' or 'Not found'.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Not Found"}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"422":{"description":"Invalid request, filter selection, UUID, geometry, range or unavailable operation context. Request-validation errors are capped at 20 items; locations at 8 parts; text parts/type at 80 and message at 160 characters. Service validation uses the same loc/type/msg shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicValidationError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":[{"loc":["query","operation"],"type":"literal_error","msg":"Illustrative sanitized validation message"}]}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"429":{"description":"Public request limit exceeded. Honor Retry-After before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Illustrative sanitized error message"}}}}},"headers":{"Retry-After":{"description":"Seconds until retry; always present on 429, present on limiter-origin 503 only.","schema":{"type":"string","pattern":"^[1-9][0-9]*$"}},"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"500":{"description":"An unhandled application error becomes the generic JSON detail 'Internal Server Error'. This outer exception response may omit Cache-Control: no-store.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Internal Server Error"}}}}}},"503":{"description":"Temporary public limiter, database or projection failure. Limiter failures include Retry-After: 1; other service failures may omit it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Illustrative sanitized error message"}}}}},"headers":{"Retry-After":{"description":"Seconds until retry; always present on 429, present on limiter-origin 503 only.","schema":{"type":"string","pattern":"^[1-9][0-9]*$"}},"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}}},"tags":["Properties"],"description":"Read one eligible public listing. Optional operation selects SALES or RENTAL context; an unavailable context returns 422. Without it, SALES is preferred when available. All examples are synthetic public-wire fixtures, not live listings. Optional fields are populated to demonstrate schema coverage; real responses may omit them. Catalog/LocalArea keys, labels, climate colors, phones, assets and addresses in examples are illustrative, not an active registry. Fetch reference data before using registry-backed filter values. Full sale example: GET /api/v1/public/properties/P9001?operation=SALES. The full example represents FULL address visibility and a fictional EXACT public point. STREET omits address_line and returns an APPROXIMATE point; HIDDEN omits location and address_line. No visibility flag is returned. See /docs/rendering-property-details#complete-sale-property-response.","security":[],"x-readme":{"explorer-enabled":false},"x-explorer-enabled":false}},"/api/v1/public/properties/{public_id}/images/{asset_id}":{"get":{"summary":"Read public property image","operationId":"property_image_api_v1_public_properties__public_id__images__asset_id__get","parameters":[{"name":"public_id","in":"path","required":true,"schema":{"type":"string","title":"Public Id"},"example":"P9001"},{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"example":"00000000-0000-4000-8000-000000009001"}],"responses":{"200":{"description":"Sanitized JPEG derivative","content":{"image/jpeg":{"schema":{"type":"string","format":"binary"}}},"headers":{"X-Content-Type-Options":{"schema":{"type":"string","const":"nosniff"}},"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"404":{"description":"Public API/media disabled, or eligible listing/profile/asset unavailable. Messages may be 'Not Found' or 'Not found'.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Not Found"}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"422":{"description":"Invalid request, filter selection, UUID, geometry, range or unavailable operation context. Request-validation errors are capped at 20 items; locations at 8 parts; text parts/type at 80 and message at 160 characters. Service validation uses the same loc/type/msg shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicValidationError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":[{"loc":["path","asset_id"],"type":"uuid_parsing","msg":"Illustrative sanitized validation message"}]}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"429":{"description":"Public request limit exceeded. Honor Retry-After before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Illustrative sanitized error message"}}}}},"headers":{"Retry-After":{"description":"Seconds until retry; always present on 429, present on limiter-origin 503 only.","schema":{"type":"string","pattern":"^[1-9][0-9]*$"}},"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"500":{"description":"An unhandled application error becomes the generic JSON detail 'Internal Server Error'. This outer exception response may omit Cache-Control: no-store.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Internal Server Error"}}}}}},"503":{"description":"Temporary public limiter, database or projection failure. Limiter failures include Retry-After: 1; other service failures may omit it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Illustrative sanitized error message"}}}}},"headers":{"Retry-After":{"description":"Seconds until retry; always present on 429, present on limiter-origin 503 only.","schema":{"type":"string","pattern":"^[1-9][0-9]*$"}},"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}}},"tags":["Media"],"description":"Return only the current sanitized JPEG derivative bound to this eligible public property and asset. A missing, revoked or unready derivative returns 404.\n\nSynthetic request (API origin remains unconfirmed):\n\n```http\nGET /api/v1/public/properties/P9001/images/00000000-0000-4000-8000-000000009001\nAccept: image/jpeg\n```\n\nSuccessful response is binary JPEG bytes, not JSON or base64.\n\n```http\nHTTP/1.1 200 OK\nContent-Type: image/jpeg\nCache-Control: no-store\nX-Content-Type-Options: nosniff\n\n[binary JPEG bytes]\n```\n\nUse only the returned gallery/thumbnail/agent photo URL. These synthetic UUIDs do not identify downloadable production images.","security":[],"x-readme":{"explorer-enabled":false},"x-explorer-enabled":false}},"/api/v1/public/agent-images/{asset_id}":{"get":{"summary":"Read public agent image","operationId":"agent_image_api_v1_public_agent_images__asset_id__get","parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"example":"00000000-0000-4000-8000-000000009002"}],"responses":{"200":{"description":"Sanitized JPEG derivative","content":{"image/jpeg":{"schema":{"type":"string","format":"binary"}}},"headers":{"X-Content-Type-Options":{"schema":{"type":"string","const":"nosniff"}},"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"404":{"description":"Public API/media disabled, or eligible listing/profile/asset unavailable. Messages may be 'Not Found' or 'Not found'.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Not Found"}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"422":{"description":"Invalid request, filter selection, UUID, geometry, range or unavailable operation context. Request-validation errors are capped at 20 items; locations at 8 parts; text parts/type at 80 and message at 160 characters. Service validation uses the same loc/type/msg shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicValidationError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":[{"loc":["path","asset_id"],"type":"uuid_parsing","msg":"Illustrative sanitized validation message"}]}}}}},"headers":{"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"429":{"description":"Public request limit exceeded. Honor Retry-After before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Illustrative sanitized error message"}}}}},"headers":{"Retry-After":{"description":"Seconds until retry; always present on 429, present on limiter-origin 503 only.","schema":{"type":"string","pattern":"^[1-9][0-9]*$"}},"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}},"500":{"description":"An unhandled application error becomes the generic JSON detail 'Internal Server Error'. This outer exception response may omit Cache-Control: no-store.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Internal Server Error"}}}}}},"503":{"description":"Temporary public limiter, database or projection failure. Limiter failures include Retry-After: 1; other service failures may omit it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"},"examples":{"publicError":{"summary":"Synthetic error shape; message text may vary","value":{"detail":"Illustrative sanitized error message"}}}}},"headers":{"Retry-After":{"description":"Seconds until retry; always present on 429, present on limiter-origin 503 only.","schema":{"type":"string","pattern":"^[1-9][0-9]*$"}},"Cache-Control":{"schema":{"type":"string","const":"no-store"}}}}},"tags":["Media"],"description":"Return a sanitized JPEG bound to the current photo of an enabled public profile and active user. Missing or disabled profiles/photos return 404.\n\nSynthetic request (API origin remains unconfirmed):\n\n```http\nGET /api/v1/public/agent-images/00000000-0000-4000-8000-000000009002\nAccept: image/jpeg\n```\n\nSuccessful response is binary JPEG bytes, not JSON or base64.\n\n```http\nHTTP/1.1 200 OK\nContent-Type: image/jpeg\nCache-Control: no-store\nX-Content-Type-Options: nosniff\n\n[binary JPEG bytes]\n```\n\nUse only the returned gallery/thumbnail/agent photo URL. These synthetic UUIDs do not identify downloadable production images.","security":[],"x-readme":{"explorer-enabled":false},"x-explorer-enabled":false}}},"components":{"schemas":{"ClimateZoneEnum":{"type":"string","enum":["NORTHERN_TENERIFE","NORTH_EAST_SANTA_CRUZ","EASTERN_COAST","TENERIFE_SOUTH","HIGH_MOUNTAINS","LA_LAGUNA_LA_OROTAVA"],"title":"ClimateZoneEnum","description":"Stable Tenerife climate zones; labels/colors live in reference data."},"ClimateZoneOption":{"properties":{"value":{"$ref":"#/components/schemas/ClimateZoneEnum"},"labels":{"additionalProperties":{"type":"string"},"type":"object","title":"Labels"},"color":{"type":"string","title":"Color"}},"additionalProperties":false,"type":"object","required":["value","labels","color"],"title":"ClimateZoneOption"},"CountRange":{"properties":{"min":{"anyOf":[{"type":"integer","minimum":0}],"title":"Min"},"max":{"anyOf":[{"type":"integer","minimum":0}],"title":"Max"}},"additionalProperties":false,"type":"object","title":"CountRange","description":"Optional properties may be omitted. Explicit null values are rejected. Ranges must be ordered. Duplicate filter selections are rejected."},"DestinationExtent":{"properties":{"south":{"type":"number","title":"South"},"west":{"type":"number","title":"West"},"north":{"type":"number","title":"North"},"east":{"type":"number","title":"East"},"version":{"type":"integer","title":"Version"}},"additionalProperties":false,"type":"object","required":["south","west","north","east","version"],"title":"DestinationExtent"},"MeasurementRange":{"properties":{"min":{"anyOf":[{"type":"number","minimum":0}],"title":"Min"},"max":{"anyOf":[{"type":"number","minimum":0}],"title":"Max"}},"additionalProperties":false,"type":"object","title":"MeasurementRange","description":"Optional properties may be omitted. Explicit null values are rejected. Ranges must be ordered. Duplicate filter selections are rejected."},"PriceRange":{"properties":{"min":{"anyOf":[{"type":"number","minimum":0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"}],"title":"Min"},"max":{"anyOf":[{"type":"number","minimum":0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"}],"title":"Max"}},"additionalProperties":false,"type":"object","title":"PriceRange","description":"Optional properties may be omitted. Explicit null values are rejected. Ranges must be ordered. Duplicate filter selections are rejected."},"PropertyDetailTypeEnum":{"type":"string","enum":["DUPLEX","PENTHOUSE","PENTHOUSE_DUPLEX","STUDIO","BUNGALOW","CORNER"],"title":"PropertyDetailTypeEnum","description":"Third-level physical detail; valid only for its parent/subtype tuple."},"PropertyFeaturesTypeEnum":{"type":"string","enum":["FLAT","HOUSE","HOUSE_INDEPENDENT","HOUSE_SEMIDETACHED","HOUSE_TERRACED","RUSTIC","GARAGE","OFFICE","PREMISES","PREMISES_COMMERCIAL","PREMISES_INDUSTRIAL","LAND","LAND_URBAN","LAND_COUNTRYBUILDABLE","LAND_COUNTRYNONBUILDABLE","STORAGE","BUILDING_HOTEL","BUILDING_COMMERCIAL","BUILDING_INDUSTRIAL","BUILDING_OFFICE","BUILDING_CHALET","BUILDING_OTHER"],"title":"PropertyFeaturesTypeEnum"},"PropertyTypeEnum":{"type":"string","enum":["HOMES","GARAGE","OFFICE","PREMISES_COMMERCIAL","LAND","STORAGE","BUILDING"],"title":"PropertyTypeEnum","description":"Top-level property type. Subtype detail is in PropertyFeaturesTypeEnum."},"PropertyWebsiteDetail":{"properties":{"public_id":{"type":"string","title":"Public Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"operation":{"type":"string","enum":["SALES","RENTAL"],"title":"Operation"},"operations":{"items":{"type":"string","enum":["SALES","RENTAL"]},"type":"array","title":"Operations"},"prices":{"items":{"$ref":"#/components/schemas/PublicOperationPrice"},"type":"array","title":"Prices"},"price":{"anyOf":[{"$ref":"#/components/schemas/PublicPrice"},{"type":"null"}]},"asking_price_per_m2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Asking Price Per M2"},"property_type":{"anyOf":[{"$ref":"#/components/schemas/PropertyTypeEnum"},{"type":"null"}]},"features_type":{"anyOf":[{"$ref":"#/components/schemas/PropertyFeaturesTypeEnum"},{"type":"null"}]},"property_detail_type":{"anyOf":[{"$ref":"#/components/schemas/PropertyDetailTypeEnum"},{"type":"null"}]},"bedrooms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Bedrooms"},"bathrooms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Bathrooms"},"total_area_m2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total Area M2"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"region":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Region"},"ubicacion":{"anyOf":[{"$ref":"#/components/schemas/PublicLocalArea"},{"type":"null"}]},"view_types":{"items":{"$ref":"#/components/schemas/ViewTypeEnum"},"type":"array","title":"View Types"},"catalogs":{"items":{"type":"string"},"type":"array","title":"Catalogs"},"location_facts":{"anyOf":[{"$ref":"#/components/schemas/PublicLocationFacts"},{"type":"null"}]},"location":{"anyOf":[{"$ref":"#/components/schemas/PublicLocation"},{"type":"null"}]},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"description_translations":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Description Translations"},"characteristics":{"$ref":"#/components/schemas/PublicCharacteristics"},"gallery":{"items":{"$ref":"#/components/schemas/PublicGalleryImage"},"type":"array","maxItems":100,"title":"Gallery"},"agent":{"anyOf":[{"$ref":"#/components/schemas/PublicAgent"},{"type":"null"}]},"address_line":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address Line"}},"additionalProperties":false,"type":"object","required":["public_id","operation","operations","prices","view_types","catalogs","characteristics","gallery"],"title":"PropertyWebsiteDetail","description":"Public projection only. Omitted optional properties are not populated; null and omission remain distinct. Money is a decimal string with two fractional digits. No CRM investment or private profile fields.","example":{"public_id":"P9001","name":"Example coastal penthouse duplex","operation":"SALES","operations":["SALES"],"prices":[{"amount":"425000.00","currency":"EUR","kind":"SALE","period":"ONE_OFF","operation":"SALES"}],"price":{"amount":"425000.00","currency":"EUR","kind":"SALE","period":"ONE_OFF"},"asking_price_per_m2":"4250.00","property_type":"HOMES","features_type":"FLAT","property_detail_type":"PENTHOUSE_DUPLEX","bedrooms":3,"bathrooms":2,"total_area_m2":100,"city":"Adeje","region":"Santa Cruz de Tenerife","ubicacion":{"key":"example-local-area","label":"Example local area","city":"Adeje"},"view_types":["SEA","MOUNTAIN"],"catalogs":["example-sale-collection"],"location_facts":{"altitude_m":120,"climate_zone":"TENERIFE_SOUTH","distance_to_sea_m":900,"distance_to_airport_km":20,"distance_to_nearest_school_km":1.2,"distance_to_nearest_healthcare_km":2.4,"short_term_rental_possible":false},"location":{"lat":28.1,"lng":-16.7,"precision":"EXACT"},"description":"Invented sale listing for frontend layout and API mocks.","description_translations":{"en":"Invented sale listing for frontend layout and API mocks.","es":"Anuncio ficticio para ejemplos de interfaz."},"characteristics":{"floor":"3","toilets":1,"living_area_m2":85,"outdoor_area_m2":15,"terrace_area_m2":15,"pool_area_m2":40,"garden_area_m2":60,"built_year":2010,"features_conservation":"GOOD","pool_type":"PUBLIC_HEATED","parking_type":"PARKING_SPACE","parking_spaces":1,"garden_type":"COMMUNAL","kitchen_type":"AMERICAN","furnishing_status":"PARTIALLY_FURNISHED","terrace_glazing":"NOT_GLAZED","window_features":["ALUMINUM","BLINDS"],"is_renovated":true,"last_renovated_year":2024,"is_new_construction":false,"has_terrace":true,"has_garden":true,"has_air_conditioning":true,"has_storage":true,"has_lift":true,"has_wardrobes":true,"has_terrace_awning":true,"has_jacuzzi":false,"has_security_door":true,"has_double_glazing":true,"has_alarm":false,"has_fireplace":false,"has_laundry_room":true,"has_solarium":true,"has_home_cinema":false},"gallery":[{"asset_id":"00000000-0000-4000-8000-000000009001","url":"/api/v1/public/properties/P9001/images/00000000-0000-4000-8000-000000009001","caption":"TERRACE","is_primary":true,"display_order":0}],"agent":{"display_name":"Example Agent","photo_url":"/api/v1/public/agent-images/00000000-0000-4000-8000-000000009002","public_phone":"+12025550101","public_email":"agent@example.invalid","whatsapp_phone":"+12025550101","preferred_contact_method":"EMAIL","preferred_contact_time":"Weekdays, 10:00–16:00 Atlantic/Canary"},"address_line":"Example Street 1 (fictional address)"}},"PropertyWebsiteFilters":{"properties":{"operation":{"type":"string","enum":["SALES","RENTAL"],"title":"Operation"},"rental_type":{"anyOf":[{"$ref":"#/components/schemas/RentalTypeEnum"}]},"city":{"anyOf":[{"type":"string","maxLength":100,"minLength":1}],"title":"City"},"area":{"anyOf":[{"type":"string","maxLength":100,"minLength":1}],"title":"Area"},"complex_name":{"anyOf":[{"type":"string","maxLength":100,"minLength":1}],"title":"Complex Name"},"ubicacion":{"anyOf":[{"items":{"type":"string","maxLength":200,"minLength":1},"type":"array"}],"title":"Ubicacion"},"property_type":{"anyOf":[{"items":{"$ref":"#/components/schemas/PropertyTypeEnum"},"type":"array"}],"title":"Property Type"},"features_type":{"anyOf":[{"items":{"$ref":"#/components/schemas/PropertyFeaturesTypeEnum"},"type":"array"}],"title":"Features Type"},"property_detail_type":{"anyOf":[{"items":{"$ref":"#/components/schemas/PropertyDetailTypeEnum"},"type":"array"}],"title":"Property Detail Type"},"catalogs":{"anyOf":[{"items":{"type":"string","maxLength":200,"minLength":1},"type":"array"}],"title":"Catalogs"},"bedrooms":{"anyOf":[{"$ref":"#/components/schemas/CountRange"}]},"bathrooms":{"anyOf":[{"$ref":"#/components/schemas/CountRange"}]},"total_area_m2":{"anyOf":[{"$ref":"#/components/schemas/MeasurementRange"}]},"price":{"anyOf":[{"$ref":"#/components/schemas/PriceRange"}]},"is_new_construction":{"anyOf":[{"type":"boolean"}],"title":"Is New Construction"},"has_terrace":{"anyOf":[{"type":"boolean"}],"title":"Has Terrace"},"has_pool":{"anyOf":[{"type":"boolean"}],"title":"Has Pool"},"has_parking":{"anyOf":[{"type":"boolean"}],"title":"Has Parking"},"has_lift":{"anyOf":[{"type":"boolean"}],"title":"Has Lift"},"sea_view":{"anyOf":[{"type":"boolean"}],"title":"Sea View"},"view_types":{"anyOf":[{"items":{"$ref":"#/components/schemas/ViewTypeEnum"},"type":"array"}],"title":"View Types"},"updated_at":{"anyOf":[{"$ref":"#/components/schemas/UpdatedRange"}]}},"additionalProperties":false,"type":"object","required":["operation"],"title":"PropertyWebsiteFilters","description":"Optional properties may be omitted. Explicit null values are rejected. Ranges must be ordered. Duplicate filter selections are rejected. RENTAL price filtering requires rental_type. Physical detail selections must fit the selected physical type/subtype. Active catalog keys are validated by the service. PENTHOUSE and DUPLEX each also match PENTHOUSE_DUPLEX; PENTHOUSE_DUPLEX matches only itself."},"PropertyWebsiteSearchRequest":{"properties":{"destination":{"type":"string","const":"TENERIFE","title":"Destination"},"area":{"oneOf":[{"$ref":"#/components/schemas/PublicBounds"},{"$ref":"#/components/schemas/PublicPolygon"}],"title":"Area","discriminator":{"propertyName":"kind","mapping":{"BOUNDS":"#/components/schemas/PublicBounds","POLYGON":"#/components/schemas/PublicPolygon"}}},"filters":{"$ref":"#/components/schemas/PropertyWebsiteFilters"},"page":{"type":"integer","minimum":1,"title":"Page","default":1},"page_size":{"type":"integer","maximum":100,"minimum":1,"title":"Page Size"},"sort":{"type":"string","const":"PUBLIC_ID_ASC","title":"Sort","default":"PUBLIC_ID_ASC"}},"additionalProperties":false,"type":"object","required":["destination","area","filters"],"title":"PropertyWebsiteSearchRequest","description":"destination, area and filters are required. Unknown properties are rejected. Integer page/page_size and boolean filters are strict. Pagination is one-based; default page_size is 24, configured maximum 100; (page-1)*page_size must not exceed 10000. These are source configuration defaults; the deployed configuration must be confirmed. An out-of-range result page returns empty items with totals."},"PropertyWebsiteSearchResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/PropertyWebsiteSummary"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"additionalProperties":false,"type":"object","required":["items","total","page","page_size","total_pages"],"title":"PropertyWebsiteSearchResponse"},"PropertyWebsiteSummary":{"properties":{"public_id":{"type":"string","title":"Public Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"operation":{"type":"string","enum":["SALES","RENTAL"],"title":"Operation"},"price":{"anyOf":[{"$ref":"#/components/schemas/PublicPrice"},{"type":"null"}]},"asking_price_per_m2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Asking Price Per M2"},"property_type":{"anyOf":[{"$ref":"#/components/schemas/PropertyTypeEnum"},{"type":"null"}]},"features_type":{"anyOf":[{"$ref":"#/components/schemas/PropertyFeaturesTypeEnum"},{"type":"null"}]},"property_detail_type":{"anyOf":[{"$ref":"#/components/schemas/PropertyDetailTypeEnum"},{"type":"null"}]},"bedrooms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Bedrooms"},"bathrooms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Bathrooms"},"total_area_m2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total Area M2"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"region":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Region"},"ubicacion":{"anyOf":[{"$ref":"#/components/schemas/PublicLocalArea"},{"type":"null"}]},"view_types":{"items":{"$ref":"#/components/schemas/ViewTypeEnum"},"type":"array","title":"View Types"},"catalogs":{"items":{"type":"string"},"type":"array","title":"Catalogs"},"location_facts":{"anyOf":[{"$ref":"#/components/schemas/PublicLocationFacts"},{"type":"null"}]},"location":{"$ref":"#/components/schemas/PublicLocation"},"thumbnail":{"anyOf":[{"$ref":"#/components/schemas/PublicThumbnail"},{"type":"null"}]}},"additionalProperties":false,"type":"object","required":["public_id","operation","view_types","catalogs","location"],"title":"PropertyWebsiteSummary","description":"Public projection only. Omitted optional properties are not populated; null and omission remain distinct. Money is a decimal string with two fractional digits. No CRM investment or private profile fields.","example":{"public_id":"P9001","name":"Example coastal penthouse duplex","operation":"SALES","price":{"amount":"425000.00","currency":"EUR","kind":"SALE","period":"ONE_OFF"},"asking_price_per_m2":"4250.00","property_type":"HOMES","features_type":"FLAT","property_detail_type":"PENTHOUSE_DUPLEX","bedrooms":3,"bathrooms":2,"total_area_m2":100,"city":"Adeje","region":"Santa Cruz de Tenerife","ubicacion":{"key":"example-local-area","label":"Example local area","city":"Adeje"},"view_types":["SEA","MOUNTAIN"],"catalogs":["example-sale-collection"],"location_facts":{"altitude_m":120,"climate_zone":"TENERIFE_SOUTH","distance_to_sea_m":900,"distance_to_airport_km":20,"distance_to_nearest_school_km":1.2,"distance_to_nearest_healthcare_km":2.4,"short_term_rental_possible":false},"location":{"lat":28.1,"lng":-16.7,"precision":"EXACT"},"thumbnail":{"asset_id":"00000000-0000-4000-8000-000000009001","url":"/api/v1/public/properties/P9001/images/00000000-0000-4000-8000-000000009001","caption":"TERRACE"}}},"PublicAgent":{"properties":{"display_name":{"type":"string","title":"Display Name"},"photo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Photo Url"},"public_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Public Phone"},"public_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Public Email"},"whatsapp_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Whatsapp Phone"},"preferred_contact_method":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preferred Contact Method"},"preferred_contact_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preferred Contact Time"}},"additionalProperties":false,"type":"object","required":["display_name"],"title":"PublicAgent"},"PublicBounds":{"properties":{"kind":{"type":"string","const":"BOUNDS","title":"Kind"},"south":{"type":"number","title":"South"},"west":{"type":"number","title":"West"},"north":{"type":"number","title":"North"},"east":{"type":"number","title":"East"}},"additionalProperties":false,"type":"object","required":["kind","south","west","north","east"],"title":"PublicBounds","description":"Named latitude/longitude bounds. south<north and west<east. Entire bounds must be inside the configured destination extent; fetch the reference endpoint. Source default extent: {\"south\": 27.9, \"west\": -17.0, \"north\": 28.7, \"east\": -16.0}."},"PublicCatalog":{"properties":{"key":{"type":"string","title":"Key"},"parent_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parent Key"},"labels":{"additionalProperties":{"type":"string"},"type":"object","title":"Labels"},"sort_order":{"type":"integer","title":"Sort Order"}},"additionalProperties":false,"type":"object","required":["key","parent_key","labels","sort_order"],"title":"PublicCatalog"},"PublicCharacteristics":{"properties":{"floor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Floor"},"toilets":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Toilets"},"living_area_m2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Living Area M2"},"outdoor_area_m2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Outdoor Area M2"},"terrace_area_m2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Terrace Area M2"},"pool_area_m2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pool Area M2"},"garden_area_m2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Garden Area M2"},"built_year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Built Year"},"features_conservation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Features Conservation"},"pool_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pool Type"},"parking_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parking Type"},"parking_spaces":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Parking Spaces"},"garden_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Garden Type"},"kitchen_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kitchen Type"},"furnishing_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Furnishing Status"},"terrace_glazing":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Terrace Glazing"},"window_features":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Window Features"},"is_renovated":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Renovated"},"last_renovated_year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Renovated Year"},"is_new_construction":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is New Construction"},"has_terrace":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Terrace"},"has_garden":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Garden"},"has_air_conditioning":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Air Conditioning"},"has_storage":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Storage"},"has_lift":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Lift"},"has_wardrobes":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Wardrobes"},"has_terrace_awning":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Terrace Awning"},"has_jacuzzi":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Jacuzzi"},"has_security_door":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Security Door"},"has_double_glazing":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Double Glazing"},"has_alarm":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Alarm"},"has_fireplace":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Fireplace"},"has_laundry_room":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Laundry Room"},"has_solarium":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Solarium"},"has_home_cinema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Home Cinema"}},"additionalProperties":false,"type":"object","title":"PublicCharacteristics"},"PublicDestination":{"properties":{"key":{"type":"string","const":"TENERIFE","title":"Key"},"extent":{"$ref":"#/components/schemas/DestinationExtent"}},"additionalProperties":false,"type":"object","required":["key","extent"],"title":"PublicDestination"},"PublicGalleryImage":{"properties":{"asset_id":{"type":"string","title":"Asset Id"},"url":{"type":"string","title":"Url"},"caption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caption","description":"Optional current image label string, for example TERRACE; not a promise of free-form descriptive alt text. UNKNOWN labels are omitted by the projection."},"is_primary":{"type":"boolean","title":"Is Primary"},"display_order":{"type":"integer","title":"Display Order"}},"additionalProperties":false,"type":"object","required":["asset_id","url","is_primary","display_order"],"title":"PublicGalleryImage"},"PublicLocalArea":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"city":{"type":"string","title":"City"}},"additionalProperties":false,"type":"object","required":["key","label","city"],"title":"PublicLocalArea"},"PublicLocation":{"properties":{"lat":{"type":"number","title":"Lat"},"lng":{"type":"number","title":"Lng"},"precision":{"type":"string","enum":["EXACT","APPROXIMATE"],"title":"Precision"}},"additionalProperties":false,"type":"object","required":["lat","lng","precision"],"title":"PublicLocation","description":"Only the policy-approved public point. APPROXIMATE is not a private exact point. Use these values as returned; never infer or retrieve private coordinates."},"PublicLocationFacts":{"properties":{"altitude_m":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Altitude M"},"climate_zone":{"anyOf":[{"$ref":"#/components/schemas/ClimateZoneEnum"},{"type":"null"}]},"distance_to_sea_m":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance To Sea M"},"distance_to_airport_km":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance To Airport Km"},"distance_to_nearest_school_km":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance To Nearest School Km"},"distance_to_nearest_healthcare_km":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance To Nearest Healthcare Km"},"short_term_rental_possible":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Short Term Rental Possible"}},"additionalProperties":false,"type":"object","title":"PublicLocationFacts"},"PublicOperationPrice":{"properties":{"amount":{"type":"string","title":"Amount"},"currency":{"type":"string","const":"EUR","title":"Currency","default":"EUR"},"kind":{"type":"string","enum":["SALE","TRANSFER","RENT"],"title":"Kind"},"period":{"type":"string","enum":["ONE_OFF","DAY","MONTH","YEAR"],"title":"Period"},"operation":{"type":"string","enum":["SALES","RENTAL"],"title":"Operation"}},"additionalProperties":false,"type":"object","required":["amount","kind","period","operation"],"title":"PublicOperationPrice"},"PublicPolygon":{"properties":{"kind":{"type":"string","const":"POLYGON","title":"Kind"},"vertices":{"items":{"$ref":"#/components/schemas/PublicVertex"},"type":"array","maxItems":101,"minItems":3,"title":"Vertices"}},"additionalProperties":false,"type":"object","required":["kind","vertices"],"title":"PublicPolygon","description":"Simple, non-zero-area polygon of distinct lat/lng vertices inside the destination extent. Edges may not self-intersect or touch. A repeated closing vertex is accepted and removed before counting; source default accepted count is 3–100 distinct vertices."},"PublicPrice":{"properties":{"amount":{"type":"string","title":"Amount"},"currency":{"type":"string","const":"EUR","title":"Currency","default":"EUR"},"kind":{"type":"string","enum":["SALE","TRANSFER","RENT"],"title":"Kind"},"period":{"type":"string","enum":["ONE_OFF","DAY","MONTH","YEAR"],"title":"Period"}},"additionalProperties":false,"type":"object","required":["amount","kind","period"],"title":"PublicPrice"},"PublicPropertyReference":{"properties":{"schema_version":{"type":"string","title":"Schema Version"},"destination":{"$ref":"#/components/schemas/PublicDestination"},"operations":{"items":{"type":"string","enum":["SALES","RENTAL"]},"type":"array","title":"Operations"},"rental_types":{"items":{"$ref":"#/components/schemas/RentalTypeEnum"},"type":"array","title":"Rental Types"},"view_types":{"items":{"$ref":"#/components/schemas/ViewTypeEnum"},"type":"array","title":"View Types"},"property_types":{"items":{"$ref":"#/components/schemas/PropertyTypeEnum"},"type":"array","title":"Property Types"},"features_types":{"items":{"$ref":"#/components/schemas/PropertyFeaturesTypeEnum"},"type":"array","title":"Features Types"},"property_detail_types":{"items":{"$ref":"#/components/schemas/PropertyDetailTypeEnum"},"type":"array","title":"Property Detail Types"},"climate_zones":{"items":{"$ref":"#/components/schemas/ClimateZoneOption"},"type":"array","title":"Climate Zones"},"catalogs":{"items":{"$ref":"#/components/schemas/PublicCatalog"},"type":"array","title":"Catalogs"},"local_areas":{"anyOf":[{"items":{"$ref":"#/components/schemas/PublicLocalArea"},"type":"array"},{"type":"null"}],"title":"Local Areas"}},"additionalProperties":false,"type":"object","required":["schema_version","destination","operations","rental_types","view_types","property_types","features_types","property_detail_types","climate_zones","catalogs"],"title":"PublicPropertyReference","example":{"schema_version":"2026-10-19.1","destination":{"key":"TENERIFE","extent":{"south":27.9,"west":-17,"north":28.7,"east":-16,"version":1}},"operations":["SALES","RENTAL"],"rental_types":["TEMPORAL","LONG_TERM","SHORT_TERM"],"view_types":["SEA","GARDEN","MOUNTAIN","STREET","NEIGHBORHOOD","POOL","SEA_AND_COAST","PANORAMIC_SEA","PANORAMIC_SEA_AND_ISLANDS","MOUNTAIN_AND_SEA","POOL_AND_GARDEN","STREET_AND_MOUNTAIN"],"property_types":["HOMES","GARAGE","OFFICE","PREMISES_COMMERCIAL","LAND","STORAGE","BUILDING"],"features_types":["FLAT","HOUSE","HOUSE_INDEPENDENT","HOUSE_SEMIDETACHED","HOUSE_TERRACED","RUSTIC","GARAGE","OFFICE","PREMISES","PREMISES_COMMERCIAL","PREMISES_INDUSTRIAL","LAND","LAND_URBAN","LAND_COUNTRYBUILDABLE","LAND_COUNTRYNONBUILDABLE","STORAGE","BUILDING_HOTEL","BUILDING_COMMERCIAL","BUILDING_INDUSTRIAL","BUILDING_OFFICE","BUILDING_CHALET","BUILDING_OTHER"],"property_detail_types":["DUPLEX","PENTHOUSE","PENTHOUSE_DUPLEX","STUDIO","BUNGALOW","CORNER"],"climate_zones":[{"value":"NORTHERN_TENERIFE","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"NORTH_EAST_SANTA_CRUZ","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"EASTERN_COAST","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"TENERIFE_SOUTH","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"HIGH_MOUNTAINS","labels":{"en":"Example climate label"},"color":"#4472d0"},{"value":"LA_LAGUNA_LA_OROTAVA","labels":{"en":"Example climate label"},"color":"#4472d0"}],"catalogs":[{"key":"example-sale-collection","parent_key":null,"labels":{"en":"Example sale collection","es":"Colección de ejemplo"},"sort_order":10}],"local_areas":[{"key":"example-local-area","label":"Example local area","city":"Adeje"}]}},"PublicThumbnail":{"properties":{"asset_id":{"type":"string","title":"Asset Id"},"url":{"type":"string","title":"Url"},"caption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caption","description":"Optional current image label string, for example TERRACE; not a promise of free-form descriptive alt text. UNKNOWN labels are omitted by the projection."}},"additionalProperties":false,"type":"object","required":["asset_id","url"],"title":"PublicThumbnail"},"PublicVertex":{"properties":{"lat":{"type":"number","maximum":90,"minimum":-90,"title":"Lat"},"lng":{"type":"number","maximum":180,"minimum":-180,"title":"Lng"}},"additionalProperties":false,"type":"object","required":["lat","lng"],"title":"PublicVertex"},"RentalTypeEnum":{"type":"string","enum":["TEMPORAL","LONG_TERM","SHORT_TERM"],"title":"RentalTypeEnum"},"UpdatedRange":{"properties":{"from":{"anyOf":[{"type":"string","format":"date-time"}],"title":"From"},"to":{"anyOf":[{"type":"string","format":"date-time"}],"title":"To"}},"additionalProperties":false,"type":"object","title":"UpdatedRange","description":"Optional properties may be omitted. Explicit null values are rejected. Ranges must be ordered. Duplicate filter selections are rejected."},"ViewTypeEnum":{"type":"string","enum":["SEA","GARDEN","MOUNTAIN","STREET","NEIGHBORHOOD","POOL","SEA_AND_COAST","PANORAMIC_SEA","PANORAMIC_SEA_AND_ISLANDS","MOUNTAIN_AND_SEA","POOL_AND_GARDEN","STREET_AND_MOUNTAIN"],"title":"ViewTypeEnum","description":"Property view type"},"PublicError":{"type":"object","required":["detail"],"properties":{"detail":{"type":"string"}}},"PublicValidationError":{"type":"object","required":["detail"],"description":"Sanitized validation locations, types and messages; no input/ctx/body echo.","properties":{"detail":{"type":"array","items":{"type":"object","required":["loc","type","msg"],"properties":{"loc":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"integer"}]}},"type":{"type":"string"},"msg":{"type":"string"}}}}}}}},"servers":[{"url":"https://website-api.example.invalid","description":"Non-routable review placeholder; deployment unverified"}],"security":[],"x-readme":{"explorer-enabled":false},"x-explorer-enabled":false}