The property JSON object
This is the reference for what you send: which fields the property object has, which ones are required, what 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 object you send
This is the complete object. Below is what is required, what is optional and what values each field accepts.
{
"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
},
// … and 42 more entries, one per property attribute
],
"publication": { … } // per-portal publishing configuration — see its own page
}
Photos, floor plan, videos and additional prices
They travel in the same JSON: you send a single object.
| Block | Shape | Note |
|---|---|---|
images | list of {url, description, main} | the URL, not the file: binaries don't travel in a JSON |
blueprint | {url} | only one per property |
videos | list of {source, description} | source is the YouTube or Matterport URL |
prices | {expensesCurrency, expensesPrice, taxCurrency, taxPrice, paymentPeriod} | maintenance fees and taxes, amounts as numbers |
altPrices | list 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
Each entry describes one piece of data. There are two families: the property's status
(propertyStatus) and the attributes — amenities, orientation, heating type and so on
(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
}
]
The value you send is key_legacy: it is the same in every country. 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.
customerSource — where the client came from
Every response that carries the customer block also carries, at the root, where it came from:
| Value | What it means |
|---|---|
account | It is your record, read with your clientRef. The normal case |
placeholder | You have not declared a record and this is filler. It only happens on /verify — an upload with no record responds 400, it does not fill in. Fix it with POST /customers |
frozen | The snapshot that property was created with (returned by GET and PUT). It is not your record as of today, and that is deliberate: it lets the GET say what data that property was published with |
It sits at the root and not inside customer on purpose: inside, it would mix with the fields you
declared yourself.
The client is NOT part of this object
Until 2026-09-30 the customer block travelled in here. Not any more: the client is declared once
per client and the properties inherit it.
👉 Clients — the POST /property-v1/customers, its
fields, the customerId we return and the branch.
⚠️ If you send customer inside this object it is ignored — like propertyId, customerId and
branchId. And with no client declared, the upload responds 400 with rule: account_required.
publication — how it gets published
Inside the same object travels a publication key with what each portal needs from your account and
from your publishing choices. It is not a field of the property: it is how you publish it.
{
"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>"
}
}
}
}
The full reference is on The publication key.
Required fields
There are 26, plus the attributes array. Everything else is optional.
Most of them are individual fields:
| Field | Type | Rule | |
|---|---|---|---|
code | string | ^[A-Za-z0-9._-]{1,30}$ | |
title | string | 1–150 caracteres | |
description | string | al menos 1 carácter | |
price | integer | 1 o más | |
currency | string | USD o ARS | |
type | integer | — | the type id — pa_key_legacy of the catalog's type group |
operation | integer | — | the operation id — pa_key_legacy of the operation group |
zone0 | integer | — | country |
zone1 | integer | — | province |
zone2 | integer | — | district or department |
address | string | al menos 1 carácter | |
zipcode | string | ^[A-Za-z0-9-]{1,10}$ | |
mapLatitude | number | -90 – 90 | see the warning below |
mapLongitude | number | -180 – 180 | see the warning below |
buildingArea | integer | 0 – 100.000 | built area, in m² |
landArea | integer | 1 – 10.000.000 | TOTAL area of the property, in m² — also for an apartment |
ambiences | integer | 0 – 50 | the rooms |
rooms | integer | 0 – 50 | ⚠️ these are bedrooms, not rooms in general |
bathrooms | integer | 0 – 50 | |
toilettes | integer | 0 – 10 | |
garage | integer | 0 – 100 | |
floors | integer | 0 – 10 | floors of the unit |
totalFloors | integer | 0 – 200 | floors of the building |
apartmentsPerFloor | integer | 0 – 50 | |
dependencies | integer | 0 – 10 | |
yearsOld | integer | 0 – 300 | age, in years |
The number for the type and the one for the operation are the same in every country — what changes from one country to another is the label. They are listed in Constants.
The two areas have different floors, and it is on purpose. landArea goes from 1 upwards
because every property occupies land; buildingArea admits 0, because a lot has no construction
and declaring it as zero is correct.
Optional fields
| Field | Type | Rule | |
|---|---|---|---|
zone3 | integer | — | locality or neighborhood |
betweenStreets | string | — | |
occupancy | integer | 1 – 50 | |
sold | boolean | — | sold |
rented | boolean | — | rented |
reserved | boolean | — | reserved |
suspended | boolean | — | listing suspended |
descriptionFormatted | string | — | the description with its line breaks; if you omit it, description is used |
conditions | string | — | terms of the operation — "Cash", "Mortgage-ready"… |
urlWebExternal | string | — | the property's URL on your own site |
mapLatitude and mapLongitude are required, and they go as numbers, not as text. They are in
the table above: if you omit them or send them as null, the property fails validation. Geocode the
address before posting.
And 0 is not "no coordinate": it is a real point in the Gulf of Guinea, so a property with
0, 0 gets published there. Validation accepts it —it is a valid number— but the listing comes out
wrong.
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.
Your token needs the property-api-verify scope. Without it, the response is 403. Request it
together with your access credentials.
See also
- The property model — stable keys, per-country catalog, what you send and what we set
- GET /property-attributes — the value catalog
- POST /properties — the creation endpoint