DEVELOPING

The property JSON object

This is the reference for what you send: which fields the property object has, which ones are required, which values each one accepts, and how to say "I don't have this data".

It is a reference for the object, not for an endpoint. To understand how a property is identified —why type and operation are stable keys and where their values come from— read The property model first.

The fields and ranges on this page come from measuring 220 real properties, not from assumptions. Wherever the real data contradicts the rule, it is noted.

38 fields are enough

You don't need to send the complete object. If you send the 38 fields below with the attributes array filled in, the response returns the entire property —82 fields— with everything else reconstructed.

you send 38 fields  →  we return 82
you send 84 fields  →  we return 82   (the same ones, identical)

It works because 46 of those 82 fields are already stated in attributes. When you send the entry {"id": "alarm", "key_legacy": "alarm", "selected": true}, you don't also need to send "alarm": true: it is the same data twice.

And the 46 come back to their place, mixed in with the rest of the property — not to a separate block.

Start with the minimal object. It is less code on your side, fewer chances to contradict yourself, and the result is exactly the same.

The minimal object

{
  "code": "DEV-V3-909181",
  "title": "Hermoso departamento luminoso con excelente ubicación y amenities completos",
  "address": "Av. Santa Fe 4271",
  "zone0": 1,
  "zone1": 2,
  "zone2": 189,
  "zone3": 973,
  "description": "Excelente propiedad ubicada en zona premium…",
  "descriptionFormatted": "Excelente propiedad ubicada en zona premium…",
  "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,
  "rented": false,
  "sold": false,
  "reserved": false,
  "suspended": false,
  "occupancy": null,
  "images": [
    { "url": "https://cdn.ejemplo.com/propiedades/909181/frente.jpg", "description": "Frente", "main": true },
    { "url": "https://cdn.ejemplo.com/propiedades/909181/living.jpg", "description": "Living comedor", "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": [  ]
}

Photos, floor plan, videos and additional prices

They travel in the same JSON. They are not property fields —internally they go elsewhere— but you send a single object and the routing is on us.

BlockShapeNote
imageslist of {url, description, main}the URL, not the file: binaries don't travel in a JSON
blueprint{url}only one per property
videoslist of {source, description}source is the YouTube or Matterport URL
prices{expensesCurrency, expensesPrice, taxCurrency, taxPrice, paymentPeriod}maintenance fees and taxes, amounts as numbers
altPriceslist of {description, currency, price}alternative prices

⚠️ The property's price and currency do not go here: they are fields of the property itself and are already listed above.

The attributes array

This is where most of the property lives. Each entry describes one piece of data, and there are four families: the type, the operation, the status, and the individual attributes.

[
  {
    "id": "individualGarage", "label": "Cochera",
    "group": "type", "group_sub": "propertyType",
    "type": "string", "key_legacy": "6", "value": 6,
    "locale": "es_AR", "country": "ar"
  },
  {
    "id": "rent", "label": "Alquiler",
    "group": "operation", "group_sub": "propertyOperation",
    "type": "string", "key_legacy": "2", "value": 2,
    "locale": "es_AR", "country": "ar"
  },
  {
    "id": "statusAverage", "label": "Estado Regular",
    "group": "propertyStatus", "group_sub": "status",
    "type": "list", "key_legacy": "8", "value": 8,
    "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"
  }
]

The value you send is key_legacy: it is the same across all 15 countries. The id, the label and the value come from your country's catalog — where to get them is explained further down.

attributes is required, and an empty list is valid. If the property has no attributes at all, send "attributes": []; what you cannot do is omit the key. Omitting it returns:

{"error": "ATTRIBUTES_REQUIRED",
 "description": "Falta la lista de atributos de la propiedad. El campo \"attributes\" es obligatorio: enviá la lista de atributos, o una lista vacía ([]) si la propiedad no tiene ninguno."}

But sending it empty has a cost: you lose the minimal object. The 46 fields that the array reconstructs are then up to you to send, one by one.

Required fields

There are 12, plus the attributes array. Everything else is optional.

Ten of them are individual fields:

FieldTypeRule
codestring1–30, no spaces: ^[A-Za-z0-9._-]{1,30}$
titlestring1–150 characters
descriptionstringat least 1 character
priceinteger1 or more
currencystringUSD or ARS
zone0integercountry
zone1integerprovince
zone2integerdistrict or department
zone3integerlocality or neighborhood
addressstringat least 1 character

And the two that complete the 12 are the type and the operation, which can be sent in two ways:

FieldHow to send it
typean attributes entry with group: "type" ← preferred · or the individual field type
operationan attributes entry with group: "operation" ← preferred · or the individual field operation

Either form is enough. If you send both and they don't match, the array wins and the individual field is ignored.

Optional fields

FieldTypeRangeNote
mapLatitude · mapLongitudenumber±90 / ±180see the warning below
buildingAreainteger1 – 100,000 m²
landAreainteger1 – 10,000,000 m²
roomsinteger0 – 50⚠️ these are bedrooms, not rooms in general
ambiencesinteger0 – 50the rooms
bathroomsinteger0 – 50
toilettesinteger0 – 10
garageinteger0 – 100
floorsinteger0 – 10floors of the unit
totalFloorsinteger0 – 200floors of the building
apartmentsPerFloorinteger0 – 50
dependenciesinteger0 – 10
yearsOldinteger0 – 300age in years
occupancyinteger1 – 50
zipcodestring1–10: ^[A-Za-z0-9-]{1,10}$
betweenStreetsstringfree
conditions · urlWebExternal · descriptionFormattedstringfree

mapLatitude and mapLongitude go as numbers, not as text, and 0 is not "no coordinate": it is a real point in the Gulf of Guinea. If you don't have the coordinate, send null or don't send the field — but never 0.

How to say "I don't have this data"

An optional field you don't have is sent as null or not sent at all: for us it is the same thing.

What is not the same is sending 0. A 0 in an area, in the age, in the number of occupants or in a coordinate is stored as the number zero — that is, as data.

Where the values come from

The enumerated fields —type, operation, status, orientations, amenities— deliberately have no fixed list on this page: they depend on the country and change whenever a new one is added.

You request them here:

GET /property-attributes?country=AR

See the full endpoint reference

It returns, for that country, everything it accepts: the text key (pa_key), the value you send (pa_key_legacy), the translated label (pa_label) and the family (pa_group_subtype).

Request the catalog for the property's country, not just one: a type may be enabled in Argentina and not in Peru.

And keep this in mind: we do not validate values against the catalog. A value that the country does not use is not rejected: it is stored, and the property ends up published with the wrong data. The catalog is not a suggestion — it is the only way to know what to send.

Verify before publishing

You can send your object and see what it produces, without creating anything:

POST /property-v1/properties/verify

It tells you whether the object is valid, which rules it breaks field by field, and what would happen on each portal. It is the same body as the creation call, without the write.

See also