Esquema de propiedad
Referencia completa del formato JSON que su API debe devolver por cada propiedad. Este documento es el contrato de datos entre su CRM y Spot2 Ingestion.
Convenciones
- Nombres de campo en snake_case.
- Fechas en formato ISO 8601 con zona horaria (ej:
2026-06-29T14:30:00Z). - Textos en UTF-8.
- Campos numéricos: punto decimal, sin separadores de miles.
- Arrays vacíos:
[], nonull. - Campos nulos (
null): equivalen a ausentes. - Campos desconocidos: se ignoran. Solo se procesan los campos documentados en este schema.
Estructura del JSON
Cada propiedad se representa como un objeto JSON con esta estructura:
{
"external_id": "prop-12345",
"property_type": "oficina",
"modality": "rent",
"title": "Oficina ejecutiva en Polanco",
"description": "Amplia oficina con vista panorámica...",
"updated_at": "2026-06-29T14:30:00Z",
"surface_m2": 120.5,
"land_m2": null,
"bedrooms": 0,
"bathrooms": 2.0,
"parking_spots": 3,
"photos": [
"https://cdn.su-crm.com/01.jpg",
"https://cdn.su-crm.com/02.jpg"
],
"price": {
"rent_price": 45000.00,
"sale_price": null,
"currency": "MXN"
},
"location": {
"latitude": 19.4326,
"longitude": -99.1332,
"street": "Av. Presidente Masaryk",
"ext_number": "123",
"int_number": "4A",
"neighborhood": "Polanco",
"city": "Ciudad de México",
"state": "Ciudad de México",
"postal_code": "11560"
},
"agent": {
"name": "Juan Pérez",
"email": "juan@broker.com",
"phone": "+525512345678"
},
"amenities": ["aire acondicionado", "elevador", "estacionamiento"],
"office": {
"floor_level": 5,
"floor_level_number": "Piso 5"
}
}
Estructura del objeto price
| Campo | Tipo | Descripción |
|---|---|---|
rent_price | number o null | Precio mensual de renta. Obligatorio si modality es rent o rent_and_sale. |
sale_price | number o null | Precio de venta. Obligatorio si modality es sale o rent_and_sale. |
currency | string | Código ISO 4217. Por defecto MXN. Ver catálogo de monedas. |
Estructura del objeto location
| Campo | Tipo | Descripción |
|---|---|---|
latitude | number o null | Latitud decimal. Recomendado. |
longitude | number o null | Longitud decimal. Recomendado. |
street | string | Calle. Obligatorio si envía coordenadas. |
ext_number | string | Número exterior. Máximo 6 caracteres. |
int_number | string | Número interior o departamento. |
neighborhood | string | Colonia o barrio. |
city | string | Ciudad. Obligatorio. |
state | string | Estado. Obligatorio. |
postal_code | string | Código postal. |
Estructura del objeto agent
| Campo | Tipo | Descripción |
|---|---|---|
name | string | Nombre del agente o corredor. |
email | string | Correo electrónico. Recomendado. |
phone | string | Teléfono. Recomendado. |
Propiedades con renta y venta
Cuando una propiedad está disponible para ambas operaciones, envíe ambos precios y establezca modality en rent_and_sale:
{
"external_id": "prop-67890",
"property_type": "local",
"modality": "rent_and_sale",
"price": {
"rent_price": 35000.00,
"sale_price": 4500000.00,
"currency": "MXN"
},
"location": {
"city": "Monterrey",
"state": "Nuevo León"
},
"updated_at": "2026-06-29T10:00:00Z"
}
Si no especifica modality, se determina automáticamente: si solo hay rent_price se asume renta, si solo sale_price venta, si ambos rent_and_sale.
Campos obligatorios
Sin estos campos, la propiedad no se publica.
| Campo | Ubicación | Tipo | Descripción |
|---|---|---|---|
external_id | raíz | string | Identificador único e inmutable. Máx 255 caracteres. |
property_type | raíz | string | Uno de los 7 valores canónicos. Ver catálogo. |
location.city | location | string | Ciudad. No vacío. |
location.state | location | string | Estado. No vacío. |
price.rent_price o price.sale_price | price | number | Al menos uno debe ser mayor a 0. |
updated_at | raíz | string | Última modificación en ISO 8601. |
Catálogo de property_type
Solo se aceptan estos 7 valores. Se reconocen variantes (ej: "oficina virtual" se clasifica como oficina), pero recomendamos usar los valores exactos.
| Valor | Descripción |
|---|---|
oficina | Oficina, despacho, corporativo |
local | Local comercial, tienda |
bodega | Bodega de almacenamiento |
nave_industrial | Nave industrial, galpón, fábrica |
terreno | Terreno, lote |
edificio | Edificio completo |
local_en_centro_comercial | Local dentro de un centro comercial |
Propiedades residenciales (casa, departamento, vivienda) se rechazan automáticamente.
Catálogo de modality
| Valor | Significado |
|---|---|
rent | Solo renta |
sale | Solo venta |
rent_and_sale | Ambas operaciones |
Catálogo de currency
Códigos ISO 4217. Por defecto MXN. Los precios se convierten a MXN usando el tipo de cambio del día.
| Código | Moneda |
|---|---|
MXN | Peso mexicano |
USD | Dólar estadounidense |
Si envía precios en moneda distinta a MXN y el tipo de cambio no está disponible, la propiedad no se publica. Recomendamos enviar precios en MXN.
Campos recomendados
Si faltan, la propiedad se publica pero con visibilidad reducida.
| Campo | Ubicación | Tipo | Descripción |
|---|---|---|---|
photos | raíz | string[] | URLs de fotos. Mínimo 1 para visibilidad pública. |
location.latitude + location.longitude | location | number | Coordenadas. Sin ellas la propiedad no aparece en el mapa. |
agent.email o agent.phone | agent | string | Al menos un medio de contacto. |
Campos opcionales
Identidad
| Campo | Ubicación | Tipo | Descripción |
|---|---|---|---|
title | raíz | string | Título del anuncio. |
description | raíz | string | Descripción libre. |
Características físicas
| Campo | Ubicación | Tipo | Validación |
|---|---|---|---|
surface_m2 | raíz | number o null | Superficie construida en m². Si > 0, mínimo 3 m². |
land_m2 | raíz | number o null | Superficie de terreno en m². |
bedrooms | raíz | integer o null | Recámaras. Máximo 20. |
bathrooms | raíz | number o null | Baños. Acepta decimales (ej: 1.5). |
parking_spots | raíz | integer o null | Cajones de estacionamiento. |
Catálogo de amenities
Lista de amenidades que reconocemos. Cada string que envíe se compara por coincidencia de términos contra esta tabla (ignorando artículos como "de", "la", "el"). Los que no coinciden se ignoran.
| Amenidad | Términos que la activan |
|---|---|
| Baños | baño, baños, bathroom |
| Wifi | wifi, internet |
| A/C | aire acondicionado, climatización |
| Estacionamiento | estacionamiento, parking, cochera |
| Bodega | bodega, almacén |
| Accesibilidad | accesibilidad, rampa |
| Luz | luz, electricidad |
| Sistema de seguridad | seguridad, vigilancia, cámaras |
| Montacargas | montacargas |
| Pizarrón | pizarrón, whiteboard |
| Elevador | elevador, ascensor |
| Terraza | terraza |
| Zona de limpieza | limpieza, cleaning |
| Divisible | divisible |
| Mezzanine | mezzanine, entrepiso |
| Cocina equipada | cocina equipada, kitchenette |
| Planta de luz | planta de luz, generador |
| Cocina | cocina |
| Loft | loft |
Ejemplos:
"aire acondicionado"→ A/C"estacionamiento para visitas"→ Estacionamiento"vigilancia 24/7"→ Sistema de seguridad"jardín"→ ignorado (no coincide)
Campos por tipo de propiedad
Algunos tipos requieren campos adicionales dentro de un objeto con el nombre del tipo.
Oficina ("property_type": "oficina" o "edificio")
El objeto office es opcional pero sus campos tienen validación si se envían.
| Campo | Ubicación | Tipo | Validación |
|---|---|---|---|
floor_level | office | integer | Número de piso (1 = planta baja). Si es 6, floor_level_number es obligatorio. |
floor_level_number | office | string | Etiqueta del piso (ej: "Piso 5"). Obligatorio si floor_level es 6. |
Ejemplo:
{
"property_type": "oficina",
"office": {
"floor_level": 5,
"floor_level_number": "Piso 5"
}
}
Industrial ("property_type": "nave_industrial" o "bodega")
| Campo | Ubicación | Tipo | Validación |
|---|---|---|---|
max_height_m | industrial | number | Altura interior máxima. Máximo 30 metros. |
min_area_divisible_m2 | industrial | number | Superficie mínima divisible. Debe ser ≤ max_area_divisible_m2. |
max_area_divisible_m2 | industrial | number | Superficie máxima divisible. Debe ser ≥ min_area_divisible_m2. |
luminaries | industrial | integer | Cantidad de luminarias. Si > 0, luminary_specs es obligatorio. |
luminary_specs | industrial | string | Especificaciones de luminarias. Obligatorio si luminaries > 0. |
Ejemplo:
{
"property_type": "nave_industrial",
"industrial": {
"max_height_m": 12,
"min_area_divisible_m2": 200,
"max_area_divisible_m2": 2000,
"luminaries": 20,
"luminary_specs": "LED industrial 200W"
}
}
Local ("property_type": "local" o "local_en_centro_comercial")
| Campo | Ubicación | Tipo | Validación |
|---|---|---|---|
price_per_sqm_min | retail | number | Precio mínimo por m². Debe ser ≤ price_per_sqm_max. |
price_per_sqm_max | retail | number | Precio máximo por m². Debe ser ≥ price_per_sqm_min. |
Ejemplo:
{
"property_type": "local",
"retail": {
"price_per_sqm_min": 200,
"price_per_sqm_max": 500
}
}
Terreno ("property_type": "terreno")
| Campo | Ubicación | Tipo | Validación |
|---|---|---|---|
land_use | terrain | string | Uso de suelo (ej: comercial, industrial, mixto). Obligatorio para terrenos. |
Ejemplo:
{
"property_type": "terreno",
"terrain": {
"land_use": "industrial"
}
}
Validaciones de precio
- Precio mínimo: renta mensual ≥ $10,000 MXN. Venta ≥ $100,000 MXN. Precios menores se rechazan.
- Precio por m²: se valida contra rangos estadísticos por tipo de propiedad y modalidad. Fuera de rango → visibilidad reducida.
- Superficie: se valida contra rangos estadísticos por tipo de propiedad. Fuera de rango → visibilidad reducida.
Conversión de moneda
Si envía precios en moneda distinta a MXN:
- Se consulta el tipo de cambio del día.
- Se convierte el precio a MXN.
- Se aplican las validaciones sobre el valor convertido.
- Si el tipo de cambio no está disponible, la propiedad se rechaza.
El precio que se muestra en Spot2 siempre está en MXN. Recomendamos convertir precios a MXN del lado de su CRM antes de enviarlos.
Schema canónico vs schema del CRM
El schema documentado aquí es el formato canónico que Spot2 ingiere después del mapeo. Su CRM puede usar nombres diferentes. Spot2 se adapta vía configuración durante la integración.
Ejemplo: Tokko → Spot2
| Spot2 (canónico) | Tokko (nativo) |
|---|---|
property_type | operation_category (mapeado vía TokkoOperationType) |
price.rent_price | operation_amount cuando operation_type = "Alquiler" |
price.sale_price | operation_amount cuando operation_type = "Venta" |
price.currency | operation_currency |
location.city | Derivado de operation_full_location |
location.latitude | geo_lat |
location.longitude | geo_long |
photos | photos[].url |
modality | Derivado de los operation_type del publication_ids_map |