DEVELOPING

El objeto JSON de la propiedad

Esta es la referencia de lo que vos mandás: qué campos tiene el objeto propiedad, cuáles son obligatorios, qué valores acepta cada uno y cómo se dice "este dato no lo tengo".

Es una referencia del objeto, no de un endpoint. Para entender cómo se identifica una propiedad —por qué el tipo y la operación son claves estables y de dónde salen sus valores— leé primero El modelo de propiedad.

El objeto que mandás

Éste es el objeto completo. Abajo está qué es obligatorio, qué es opcional y qué valores acepta cada campo.

{
  "code": "DEV-V3-909181",
  "type": 6,
  "operation": 2,
  "title": "Hermoso departamento luminoso con excelente ubicación y amenities completos",
  "address": "Av. Santa Fe 4271",
  "mapLatitude": -34.5828,
  "mapLongitude": -58.4206,
  "zone0": 1,
  "zone1": 2,
  "zone2": 189,
  "description": "Excelente propiedad ubicada en zona premium con fácil acceso a transporte público, comercios y servicios. Ideal para vivir o invertir.\n\nCuenta con todos los servicios y amenities modernos. Perfecta para familias o inversión.\n\nUbicación estratégica con fácil acceso a centros comerciales, escuelas y transporte público.",
  "descriptionFormatted": "Excelente propiedad ubicada en zona premium con fácil acceso a transporte público, comercios y servicios. Ideal para vivir o invertir.\n\nCuenta con todos los servicios y amenities modernos. Perfecta para familias o inversión.\n\nUbicación estratégica con fácil acceso a centros comerciales, escuelas y transporte público.",
  "zipcode": "1684",
  "betweenStreets": "Entre Av. Pueyrredón y Av. Coronel Díaz",
  "urlWebExternal": "https://ejemplo-inmobiliaria.com/propiedad-dev",
  "conditions": "Contado",
  "yearsOld": 16,
  "totalFloors": 16,
  "apartmentsPerFloor": 3,
  "floors": 2,
  "buildingArea": 126,
  "landArea": 189,
  "ambiences": 2,
  "rooms": 3,
  "dependencies": 1,
  "bathrooms": 1,
  "toilettes": 2,
  "garage": 2,
  "currency": "USD",
  "price": 142410,
  "zone3": 973,
  "rented": false,
  "sold": false,
  "reserved": false,
  "suspended": false,
  "occupancy": null,
  "images": [
    {
      "url": "https://cdn.ejemplo.com/propiedades/909181/foto-1.jpg",
      "description": "Imagen principal",
      "main": true
    },
    {
      "url": "https://cdn.ejemplo.com/propiedades/909181/foto-2.jpg",
      "description": "Imagen 2",
      "main": false
    },
    {
      "url": "https://cdn.ejemplo.com/propiedades/909181/foto-3.jpg",
      "description": "Imagen 3",
      "main": false
    }
  ],
  "blueprint": {
    "url": "https://cdn.ejemplo.com/propiedades/909181/plano.pdf"
  },
  "videos": [
    {
      "source": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
      "description": "Recorrido"
    }
  ],
  "prices": {
    "expensesCurrency": "ARS",
    "expensesPrice": 500,
    "taxCurrency": "ARS",
    "taxPrice": 200,
    "paymentPeriod": 1
  },
  "altPrices": [
    {
      "description": "Alquiler por semana",
      "currency": "ARS",
      "price": 100000
    }
  ],
  "attributes": [
    {
      "locale": "es_AR",
      "country": "ar",
      "id": "accessible",
      "label": "Accesible",
      "group": "propertyAttribute",
      "group_sub": "label",
      "group_subtype": "ammenities",
      "type": "bool",
      "key_legacy": "accessible",
      "selected": true,
      "status": true
    },
    {
      "locale": "es_AR",
      "country": "ar",
      "id": "statusAverage",
      "label": "Estado Regular",
      "group": "propertyStatus",
      "group_sub": "status",
      "type": "list",
      "key_legacy": "8",
      "value": 8
    },
    // … y 42 entradas más, una por cada atributo de la propiedad
  ],
  "publication": { … }  // la configuración de publicación por portal — ver su propia página
}

Las fotos, el plano, los videos y los precios accesorios

Van en el mismo JSON: mandás un objeto solo.

BloqueFormaNota
imageslista de {url, description, main}la URL, no el archivo: el binario no viaja en un JSON
blueprint{url}uno solo por propiedad
videoslista de {source, description}source es la URL de YouTube o Matterport
prices{expensesCurrency, expensesPrice, taxCurrency, taxPrice, paymentPeriod}expensas e impuestos, montos como número
altPriceslista de {description, currency, price}precios alternativos

⚠️ El price y la currency de la propiedad no van acá: son campos del inmueble y ya están más arriba.

El arreglo attributes

Cada entrada describe un dato. Hay dos familias: el estado de la propiedad (propertyStatus) y los atributos — amenidades, orientación, tipo de calefacción y demás (propertyAttribute).

[
  {
    "locale": "es_AR",
    "country": "ar",
    "id": "accessible",
    "label": "Accesible",
    "group": "propertyAttribute",
    "group_sub": "label",
    "group_subtype": "ammenities",
    "type": "bool",
    "key_legacy": "accessible",
    "selected": true,
    "status": true
  },
  {
    "locale": "es_AR",
    "country": "ar",
    "id": "statusAverage",
    "label": "Estado Regular",
    "group": "propertyStatus",
    "group_sub": "status",
    "type": "list",
    "key_legacy": "8",
    "value": 8
  }
]

El valor que mandás es key_legacy: es el mismo en todos los países. El id, el label y el value salen del catálogo de tu país — de dónde sacarlos está más abajo.

attributes es obligatorio, y una lista vacía es válida. Si la propiedad no tiene ningún atributo mandá "attributes": []; lo que no se puede es omitir la clave.

customerSource — de dónde salió el cliente

Toda respuesta que trae el bloque customer trae también, en la raíz, de dónde salió:

ValorQué significa
accountEs tu ficha, la leímos con tu clientRef. Lo normal
placeholderNo declaraste ficha y esto es relleno. Sólo pasa en /verify — el alta sin ficha responde 400, no rellena. Se arregla con POST /customers
frozenEl snapshot con el que esa propiedad se dio de alta (lo devuelven el GET y el PUT). No es tu ficha de hoy, y es deliberado: así el GET dice con qué datos se publicó esa propiedad

Está en la raíz y no dentro de customer a propósito: adentro se mezclaría con los campos que declaraste vos.

El cliente NO es parte de este objeto

Hasta el 2026-09-30 el bloque customer viajaba acá adentro. Ya no: el cliente se declara una vez y sus propiedades lo heredan.

👉 Clientes — el POST /property-v1/customers, sus campos, el customerId que te devolvemos y la sucursal.

⚠️ Si mandás customer dentro de este objeto, se ignora — como propertyId, customerId y branchId. Y sin cliente declarado, el alta responde 400 con rule: account_required.

publication — cómo se publica

Dentro del mismo objeto viaja una clave publication con lo que cada portal necesita de tu cuenta y de tus elecciones de publicación. No es un campo del inmueble: es cómo lo publicás.

{
  "publication": {
    "api": {
      "argenprop": {
        "advertiserId": 99999,
        "visible": true,
        "token": "<tu-token-de-argenprop>"
      },
      "zonaprop": {
        "plan": {
          "plan": "SUPERDESTACADO"
        },
        "token": "<tu-token-de-zonaprop>"
      },
      "cabaprop": {
        "branchOfficeId": 42,
        "token": "<tu-token-de-cabaprop>"
      },
      "mercadolibre": {
        "listingTypeId": "gold_special",
        "condition": "used",
        "token": "<tu-token-de-mercadolibre>"
      }
    }
  }
}

La referencia completa está en La clave publication.

Campos obligatorios

Son 26, más el arreglo attributes. Todo lo demás es opcional.

La mayoría son campos sueltos:

CampoTipoRegla
codestring^[A-Za-z0-9._-]{1,30}$
titlestring1–150 caracteres
descriptionstringal menos 1 carácter
priceinteger1 o más
currencystringUSD o ARS
typeinteger—el id del tipo — pa_key_legacy del grupo type del catálogo
operationinteger—el id de la operación — pa_key_legacy del grupo operation
zone0integer—país
zone1integer—provincia
zone2integer—partido o departamento
addressstringal menos 1 carácter
zipcodestring^[A-Za-z0-9-]{1,10}$
mapLatitudenumber-90 – 90ver el aviso de abajo
mapLongitudenumber-180 – 180ver el aviso de abajo
buildingAreainteger0 – 100.000superficie construida, en m²
landAreainteger1 – 10.000.000superficie TOTAL de la propiedad, en m² — también en un departamento
ambiencesinteger0 – 50los ambientes
roomsinteger0 – 50⚠️ son dormitorios, no ambientes
bathroomsinteger0 – 50
toilettesinteger0 – 10
garageinteger0 – 100
floorsinteger0 – 10plantas de la unidad
totalFloorsinteger0 – 200pisos del edificio
apartmentsPerFloorinteger0 – 50
dependenciesinteger0 – 10
yearsOldinteger0 – 300antigüedad, en años

El número del tipo y el de la operación es el mismo en todos los países — lo que cambia de un país a otro es la etiqueta. Los tenés listados en Constantes.

zone3 no siempre existe, y por eso es opcional. Las zonas de Capital Federal —Recoleta, Caballito, Palermo— tienen tres niveles: el barrio es el último. En esos casos mandá zone0, zone1 y zone2, y dejá zone3 afuera. Lo vas a notar en el catálogo de zonas: el code viene con tres segmentos en vez de cuatro.

Las dos superficies tienen pisos distintos, y es a propósito. landArea va de 1 en adelante porque toda propiedad ocupa terreno; buildingArea admite 0, porque un lote no tiene construcción y declararlo en cero es correcto.

Campos opcionales

CampoTipoRegla
zone3integer—localidad o barrio
betweenStreetsstring—
occupancyinteger1 – 50
soldboolean—vendida
rentedboolean—alquilada
reservedboolean—reservada
suspendedboolean—publicación suspendida
descriptionFormattedstring—la descripción con sus saltos de línea; si no la mandás se usa description
conditionsstring—condiciones de la operación — "Contado", "Apto crédito"…
urlWebExternalstring—la URL de la propiedad en tu propio sitio

mapLatitude y mapLongitude son obligatorias, y van como número, no como texto. Están en la tabla de arriba: si las omitís o las mandás en null, la propiedad no pasa la validación. Geocodificá la dirección antes de postear.

Y el 0 no es "sin coordenada": es un punto real en el Golfo de Guinea, así que una propiedad con 0, 0 se publica ahí. La validación lo acepta —es un número válido— pero el aviso sale mal.

Cómo se dice "no tengo este dato"

Un campo opcional que no tenés se manda en null o no se manda: para nosotros es lo mismo.

Lo que no es lo mismo es mandar 0. Un 0 en una superficie, en la antigüedad, en la cantidad de ocupantes o en una coordenada se guarda como el número cero — o sea, como un dato.

De dónde salen los valores

Los campos enumerados —el tipo, la operación, el estado, las orientaciones, los amenities— no tienen una lista fija en esta página a propósito: dependen del país y cambian cuando se agrega uno nuevo.

Los pedís acá:

GET /property-attributes?country=AR

Ver la referencia completa del endpoint

Te devuelve, para ese país, todo lo que acepta: la clave en texto (pa_key), el valor que mandás (pa_key_legacy), la etiqueta traducida (pa_label) y la familia (pa_group_subtype).

Pedí el catálogo del país de la propiedad, no de uno solo: un tipo puede estar habilitado en Argentina y no en Perú.

Y tenelo presente: no validamos los valores contra el catálogo. Un valor que ese país no usa no se rechaza: se guarda, y la propiedad queda publicada con un dato equivocado. El catálogo no es una sugerencia — es la única forma de saber qué mandar.

Verificá antes de publicar

Podés mandar tu objeto y ver qué produce, sin dar de alta nada:

POST /property-v1/properties/verify

Te dice si el objeto es válido, qué reglas incumple campo por campo, y qué pasaría en cada portal. Es el mismo cuerpo del alta, sin la escritura.

Tu token necesita el scope property-api-verify. Sin él, la respuesta es 403. Pedilo junto con tus credenciales de acceso.

Ver también