BETA

POST /properties/verify

Mandás el objeto de una propiedad y te contestamos tres cosas:

  1. Si el objeto es válido según el contrato de Mapaprop, y qué le falta si no lo es.
  2. Qué entendimos de lo que mandaste — cuántos campos reconstruimos de tu arreglo attributes.
  3. Si cada portal lo podría publicar, y cuando no, exactamente qué le falta y de quién es el problema.

Este endpoint no crea, no modifica y no publica nada. No deja rastro. Es para que ajustes tu objeto antes de integrarte, tantas veces como quieras.

Está en beta. La forma de la respuesta puede cambiar mientras dure esta etapa. Los cambios se anuncian antes en esta página.

Para qué sirve

Integrarse a varios portales tiene un problema que aparece tarde: mandás un objeto que te parece completo, se publica, y recién ahí ves que el aviso salió sin precio, sin pileta o con el tipo equivocado — porque cada portal pide cosas distintas y se calla lo que no entiende.

Este endpoint te deja ver eso antes de publicar, sin crear nada y sin necesidad de tener las cuentas de los portales conectadas.

Resource information
AuthenticationRequerida (JWT) — scope property-api-verify
HTTP MethodPOST
ResponseJSON
Version1

Resource URL

https://property-api.mapaprop.com/property-v1/properties/verify

Autenticación

Se pide un token OAuth2 y el scope property-api-verify.

POST /property-v1/properties/verify
Host: property-api.mapaprop.com
Content-Type: application/json
Authorization: Bearer {access_token}

El token se obtiene como cualquier otro: POST /api/action/oauth2-v1/authorize.

Los scopes viajan firmados dentro del token. Si te agregamos un scope después de que generaste el tuyo, hay que generarlo de nuevo para que tome efecto — y generar uno nuevo invalida el anterior. Pedí de entrada todos los scopes que vayas a necesitar.

El cuerpo de la petición

{
  "canonical": { …el objeto de la propiedad… },
  "portals": ["argenprop", "zonaprop", "cabaprop"]
}
ClaveObligatorioQué es
canonicalsíEl objeto de la propiedad. Se acepta property como nombre alternativo
portalsnoQué portales evaluar. Si no lo mandás, se evalúan todos

El objeto que va en canonical es el mismo de siempre: El objeto JSON de la propiedad.

Si mandás un portal que no existe, la petición falla con un 400 en vez de ignorarlo en silencio.

Qué portales te reporta

Si en publication.api declarás…La respuesta trae…
Uno o varios portalessólo ésos
Nada (no mandás publication)todos

La idea es que no te lleguen problemas de un portal que no configuraste. Si ya declaraste Argenprop y nada más, Zonaprop no aparece en la respuesta ni cuenta en el summary.

Y si todavía no configuraste ninguno, los ves todos: es el caso de quien está evaluando la integración y quiere ver cómo se convierte su objeto en cada portal antes de decidir.

Si querés acotar la respuesta sin declarar la configuración, usá portals en el cuerpo de la petición. Son dos cosas distintas: portals dice qué querés mirar, publication dice qué tenés configurado.

publication — la configuración de publicación, dentro del objeto

Dentro de canonical podés mandar una clave publication con lo que cada portal necesita de tu cuenta y de tus elecciones de publicación. No es un campo de la propiedad: es cómo la publicás.

{
  "publication": {
    "api": {
      "argenprop": { "advertiserId": 99999, "visible": true },
      "zonaprop": {
        "plan": { "plan": "SUPERDESTACADO" },
        "branch": { "custId": 1, "email": "contacto@ejemplo.com", "name": "Inmobiliaria", "phone1": "1144445555" }
      },
      "cabaprop": { "branchOfficeId": 42 }
    }
  }
}
PortalCampos
argenpropadvertiserId (number) · visible (boolean)
zonapropplan (object) · branch (object)
cabapropbranchOfficeId (number)
mercadolibrelistingTypeId (string) · condition (string) · sellerContact (object)

Cada portal acepta además un token (string), que se valida de forma y nunca de validez: este endpoint no verifica cuentas. Su valor no aparece en ninguna parte de la respuesta.

publication no viaja a los portales como un campo más: se consume acá y se descarta.

La referencia completa —los dos niveles, qué pasa si mandás algo que no corresponde, y el detalle del token— está en su propia página: La clave publication.

La respuesta

{
  "mode": "client",
  "keyUsed": "canonical",
  "object": {
    "valid": true,
    "contract": [],
    "mapapropZone": "1-2-189-973",
    "conflicts": [],
    "rebuiltFromAttributes": {
      "fields": 22,
      "amenities": 36
    },
    "unresolved": []
  },
  "portals": {
    "argenprop": {
      "status": "fields_complete",
      "requiredFieldsComplete": true,
      "connection": "not_verified",
      "zone": {
        "sent": {
          "code": "1-2-189-973",
          "level": 3
        },
        "publishingTo": "Mar del Plata",
        "status": "mapped"
      },
      "blockers": [],
      "pendingAtPublishTime": [],
      "completeness": {
        "percentage": 100,
        "informed": 3,
        "supportedByThisType": 3
      }
    },
    "zonaprop": {
      "status": "fields_complete",
      "requiredFieldsComplete": true,
      "connection": "not_verified",
      "zone": {
        "sent": {
          "code": "1-2-189-973",
          "level": 3
        },
        "publishingTo": "General Pueyrredón",
        "status": "mapped"
      },
      "blockers": [],
      "pendingAtPublishTime": []
    },
    "cabaprop": {
      "status": "fields_complete",
      "requiredFieldsComplete": true,
      "connection": "not_verified",
      "zone": {
        "sent": {
          "code": "1-2-189-973",
          "level": 3
        },
        "status": "not_mapped",
        "message": "Todavía no tenemos mapeada esta zona para cabaprop. Escribinos con el código de zona y la publicamos: el mapeo queda hecho para siempre."
      },
      "blockers": [],
      "pendingAtPublishTime": []
    },
    "mercadolibre": {
      "status": "coming_soon",
      "message": "MercadoLibre: disponible pronto. La integración todavía no está habilitada en este endpoint.",
      "requiredFieldsComplete": false
    }
  },
  "summary": {
    "complete": 3,
    "of": 4
  }
}

object — qué pasó con tu objeto

CampoQué dice
validSi el objeto cumple el contrato de Mapaprop
contractLo que no cumple: field, rule y el detalle. Vacío si valid es true
mapapropZoneLa zona que resolvimos, como zone0-zone1-zone2-zone3
conflictsCampos donde tu attributes contradice al campo suelto. Gana attributes
rebuiltFromAttributesCuántos campos y amenidades reconstruimos de tu arreglo attributes
unresolvedEjes que no pudimos resolver (por ejemplo el tipo, si falta el catálogo del país)

conflicts merece atención: si mandás "type": 23 y tu attributes dice "Departamento", se publica como Departamento. No es un error, es la regla — pero si no era lo que querías, lo ves acá en vez de en el aviso.

portals — qué dice cada portal

CampoQué dice
statusEl veredicto. Valores abajo
requiredFieldsCompleteSi los obligatorios del objeto están todos
connectionconnected · not_connected · not_verified
zoneQué zona mandaste y en cuál vamos a publicar. Abajo
blockersLo que falta en el objeto para poder publicar
pendingAtPublishTimeLo que falta para publicar, pero no es del objeto (plan, sucursal, zona mapeada)
completenessCuántos atributos informaste de los que ese portal soporta para ese tipo

Valores de status:

ValorSignifica
fields_completeEl objeto tiene todo lo que ese portal necesita
missing_dataFalta un dato. Mirá blockers — hay algo que vos podés arreglar
not_supportedEl portal no soporta algo de esta propiedad. No lo podés arreglar mandando más datos
coming_soonLa integración todavía no está habilitada en este endpoint

Algunos portales no producen payload hasta tener su configuración: Zonaprop necesita el plan y los datos de la sucursal para armar el aviso. En esos casos el portal aparece con su estado y sus pendingAtPublishTime, pero sin el mapeo — no porque tu objeto esté mal, sino porque todavía falta el dato de cuenta con el que se construye.

Los blockers que vienen de publication traen además un ejemplo concreto de cómo se arreglan, pegado al mensaje: se espera number · ejemplo: "publication": { "api": { "argenprop": { "advertiserId": 99999 } } }. Ver La clave publication.

Cada blocker trae:

{ "field": "price",
  "kind": "missing",
  "message": "`price` es obligatorio en el objeto de Mapaprop y no vino…",
  "youCanFixIt": true }

youCanFixIt contesta la única pregunta que importa de un blocker: ¿esto lo arreglo yo mandando más datos, o es una limitación del portal? Si es true, mandá el dato. Si es false, ese portal no admite lo que le estás pidiendo y no hay JSON que lo resuelva.

blockers y pendingAtPublishTime son cosas distintas a propósito. Un objeto perfecto al que sólo le falta elegir el plan no es un objeto incompleto: es una publicación sin configurar. Por eso pendingAtPublishTime no afecta a requiredFieldsComplete ni al status.

completeness mide otra cosa que status: cuántos atributos opcionales informaste de los que ese portal soporta para ese tipo de propiedad. Podés tener completeness: 100% y missing_data al mismo tiempo — significa que informaste todos los atributos que el portal admite, pero te falta un campo obligatorio.

zone — en qué zona vamos a publicar

Cada portal tiene su propio mapa de zonas, y nosotros mantenemos la traducción entre tu zona de Mapaprop y la de ese portal. zone te muestra las dos puntas:

{ "sent": { "code": "1-2-189-973", "level": 3 },
  "publishingTo": "Mar del Plata",
  "status": "mapped" }
CampoQué dice
sent.codeLa zona que mandaste, tal como la armamos con tus zone0…zone3
sent.levelHasta qué nivel llega ese código: 2 es el partido entero, 3 baja a la localidad
sent.nameEl nombre de tu zona, si mandaste la descripción del nivel correspondiente
publishingToEl nombre de la zona del portal donde va a salir tu aviso
statusmapped · not_mapped · not_sent · not_verified

Los estados:

ValorSignifica
mappedResolvimos la zona. publishingTo te dice dónde va a salir
not_mappedTu zona es válida, pero todavía no la tenemos mapeada a ese portal. Trae un message con qué hacer
not_sentNo mandaste la zona en el objeto
not_verifiedNo llegamos a consultar el mapeo, así que no afirmamos nada

Mirá publishingTo aunque el estado sea mapped. Es el nombre público de la zona del portal: si mandaste una zona y ahí aparece otra, el aviso va a salir en ese otro lugar. Escribinos y lo corregimos — sos el único que puede darse cuenta, porque sos el que conoce la propiedad.

Un 0 al final del código no significa que falte un nivel: 1-2-201-0 es el partido entero, y es un destino de publicación válido por sí mismo. Por eso level cuenta hasta el último número distinto de cero.

summary

{ "summary": { "complete": 3, "of": 4 } }

Cuántos portales tienen los obligatorios completos, sobre el total evaluado.

Los campos obligatorios de Mapaprop mandan sobre los del portal

Esto es lo más importante de entender del endpoint.

Mapaprop tiene su propio contrato de campos obligatorios, y no depende de lo que pida cada portal. Si falta uno de esos campos, ningún portal queda en fields_complete — aunque ese portal en particular no lo exija.

Ejemplo: Argenprop no exige el precio para armar su payload. Igual, si no mandás price:

{
  "object": {
    "valid": false,
    "contract": [ { "field": "price", "rule": "required", "detail": "" } ]
  },
  "portals": {
    "argenprop": {
      "status": "missing_data",
      "requiredFieldsComplete": false,
      "blockers": [
        { "field": "price",
          "kind": "missing",
          "message": "`price` es obligatorio en el objeto de Mapaprop y no vino. Sin él no se publica en ningún portal, lo exija o no este portal en particular.",
          "youCanFixIt": true }
      ]
    }
  },
  "summary": { "complete": 0, "of": 4 }
}

La lista completa de campos obligatorios está en El objeto JSON de la propiedad.

Sólo la ausencia de un obligatorio bloquea. Un campo presente pero con un formato incorrecto aparece en object.contract e informa sin bloquear — para que puedas ir corrigiendo sin que el endpoint se vuelva inusable. Revisá siempre object.contract, no sólo el summary.

No hace falta tener el portal conectado

El campo connection te dice si la cuenta de ese portal está conectada, pero no condiciona nada: el objeto se mapea igual y los blockers se calculan igual.

ValorSignifica
connectedLa cuenta está conectada
not_connectedNo hay cuenta conectada para ese portal
not_verifiedNo se pudo verificar el estado de la conexión

Es un dato al costado, y sigue importando: un objeto impecable no se publica si la cuenta no está conectada. Pero para perfeccionar tu objeto no necesitás tener ninguna.

Errores

CódigoCuándo
400Falta el body, no es JSON válido, falta canonical/property, o pediste un portal que no existe
403Al token le falta el scope property-api-verify
{ "error": "Portales desconocidos: idealista. Válidos: argenprop, zonaprop, cabaprop, mercadolibre, mapaprop" }

MercadoLibre

Sale siempre como coming_soon. La integración existe pero todavía no está habilitada en este endpoint, y preferimos no mostrarte un mapeo sin verificar: lo tomarías por bueno.

Cómo usarlo

  1. Mandá tu objeto tal como lo tenés hoy.
  2. Mirá primero object.valid y object.contract. Si hay un obligatorio faltando, arreglá eso — va a estar bloqueando todos los portales a la vez.
  3. Mirá object.conflicts. Si aparece algo, tu attributes y tus campos sueltos se están contradiciendo, y gana attributes.
  4. Portal por portal, resolvé los blockers con youCanFixIt: true.
  5. Los youCanFixIt: false no los podés resolver: son límites del portal.
  6. Repetí. No se crea nada, así que probá tantas veces como necesites.

¿Necesitás ayuda? Contactá al Soporte técnico de Mapaprop