POST /properties/verify
Você envia o objeto de um imóvel e respondemos três coisas:
- Se o objeto é válido de acordo com o contrato da Mapaprop, e o que falta se não for.
- O que entendemos do que você enviou — quantos campos reconstruímos do seu array
attributes. - Se cada portal poderia publicá-lo, e quando não, exatamente o que falta e de quem é o problema.
Este endpoint não cria, não modifica e não publica nada. Não deixa rastro. Serve para você ajustar o seu objeto antes de se integrar, quantas vezes quiser.
Está em beta. A forma da resposta pode mudar enquanto durar esta etapa. As mudanças são anunciadas nesta página com antecedência.
Para que serve
Integrar-se a vários portais tem um problema que aparece tarde: você envia um objeto que lhe parece completo, ele é publicado, e só então você vê que o anúncio saiu sem preço, sem piscina ou com o tipo errado — porque cada portal pede coisas diferentes e se cala sobre o que não entende.
Este endpoint deixa você ver isso antes de publicar, sem criar nada e sem precisar ter as contas dos portais conectadas.
| Resource information | |
|---|---|
| Authentication | Obrigatória (JWT) — scope property-api-verify |
| HTTP Method | POST |
| Response | JSON |
| Version | 1 |
Resource URL
https://property-api.mapaprop.com/property-v1/properties/verify
Autenticação
É exigido um token OAuth2 e o scope property-api-verify.
POST /property-v1/properties/verify
Host: property-api.mapaprop.com
Content-Type: application/json
Authorization: Bearer {access_token}
O token é obtido como qualquer outro: POST /api/action/oauth2-v1/authorize.
Os scopes viajam assinados dentro do token. Se adicionarmos um scope depois de você ter gerado o seu, ele precisa ser gerado de novo para ter efeito — e gerar um novo invalida o anterior. Peça desde o início todos os scopes de que você vai precisar.
O corpo da requisição
O verify funciona SEM você ter declarado seu cliente. É um testador: valida o token e descreve o
objeto, não cadastra nada. Se você ainda não o declarou, ele preenche os dados do cliente com um
placeholder, e avisa em customerSource — assim você pode testar o objeto no primeiro dia, sem
nenhum passo anterior e sem confundir o preenchimento com os seus dados.
⚠️ Onde ela É necessária é no cadastro: POST /property-v1/properties responde 400 com
rule: account_required se a conta não tiver cliente declarado. Declara-se UMA vez com
POST /property-v1/customers. Os imóveis que você carregar depois a herdam; os já carregados
mantêm o contato com que foram criados.
⚠️ Um detalhe do placeholder: o country não é preenchido. Um valor de preenchimento ali seria
indistinguível de uma resposta real, e é o dado que não conviria adivinhar.
{
"canonical": { …el objeto de la propiedad… },
"portals": ["argenprop", "zonaprop", "cabaprop"]
}
| Chave | Obrigatório | O que é |
|---|---|---|
canonical | sim | O objeto do imóvel. property é aceito como nome alternativo |
portals | não | Quais portais avaliar. Se você omitir, todos são avaliados |
O objeto que vai em canonical é o de sempre:
O objeto JSON do imóvel.
Se você enviar um portal que não existe, a requisição falha com um 400 em vez de ignorá-lo em silêncio.
Quais portais são reportados
Se em publication.api você declarar… | A resposta traz… |
|---|---|
| Um ou vários portais | apenas esses |
Nada (você não envia publication) | todos |
A ideia é que não cheguem até você problemas de um portal que você não configurou. Se já declarou o
Argenprop e mais nada, o Zonaprop não aparece na resposta nem conta no summary.
E se você ainda não configurou nenhum, vê todos: é o caso de quem está avaliando a integração e quer ver como o seu objeto se converte em cada portal antes de decidir.
Se você quiser restringir a resposta sem declarar a configuração, use portals no corpo da
requisição. São duas coisas diferentes: portals diz o que você quer olhar, publication diz o
que você tem configurado.
publication — a configuração de publicação, dentro do objeto
Dentro de canonical você pode enviar uma chave publication com o que cada portal precisa da sua
conta e das suas escolhas de publicação. Não é um campo do imóvel: é como você o publica.
{
"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 }
}
}
}
O branch do Zonaprop e o sellerContact do MercadoLibre são preenchidos automaticamente a partir
do cliente que você declarou: não é preciso enviá-los. Estão no exemplo porque, se você os enviar,
eles ganham — o preenchimento automático tem a menor precedência de todas.
| Portal | Campos |
|---|---|
argenprop | advertiserId (number) · visible (boolean) |
zonaprop | plan (object) · branch (object) |
cabaprop | branchOfficeId (number) |
mercadolibre | listingTypeId (string) · condition (string) · sellerContact (object) |
Cada portal aceita também um token (string), que é validado na forma e nunca na validade: este
endpoint não verifica contas. O seu valor não aparece em nenhuma parte da resposta.
publication não viaja aos portais como mais um campo: é consumido aqui e descartado.
A referência completa —os dois níveis, o que acontece se você enviar algo que não corresponde, e o
detalhe do token— está na sua própria página:
A chave publication.
A resposta
A resposta traz o clientRef, o mesmo que você enviou no envelope. Nós o devolvemos nos seis
caminhos (verify, cadastro, consulta, listagem, edição e exclusão) para que você possa cruzá-lo com a sua
base sem ter que lembrar com qual clientRef perguntou.
{
"mode": "client",
"object": {
"valid": true,
"contract": [],
"mapapropZone": "1-2-189-973",
"conflicts": [],
"conflicts": []
},
"portals": {
"argenprop": {
"status": "fields_complete",
"connection": "not_verified",
"zone": {
"sent": {
"code": "1-2-189-973",
"level": 3
},
"publishingTo": "Mar del Plata",
"status": "mapped"
},
"blockers": [],
"pendingAtPublishTime": []
},
"zonaprop": {
"status": "fields_complete",
"connection": "not_verified",
"zone": {
"sent": {
"code": "1-2-189-973",
"level": 3
},
"publishingTo": "General Pueyrredón",
"status": "mapped"
},
"blockers": [],
"pendingAtPublishTime": []
},
"cabaprop": {
"status": "fields_complete",
"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."
}
},
"summary": {
"complete": 3,
"of": 4
}
}
object — o que aconteceu com o seu objeto
| Campo | O que diz |
|---|---|
valid | Se o objeto cumpre o contrato da Mapaprop |
contract | O que não cumpre: field, rule e o detalhe. Vazio se valid for true |
mapapropZone | A zona que resolvemos, como zone0-zone1-zone2-zone3 |
conflicts | Campos onde o seu attributes contradiz o campo avulso. attributes ganha |
conflicts merece atenção: se você envia "type": 23 e o seu attributes diz "Departamento", é
publicado como Departamento. Não é um erro, é a regra — mas se não era o que você queria, você vê
aqui em vez de no anúncio.
portals — o que cada portal diz
| Campo | O que diz |
|---|---|
status | O veredito. Valores abaixo |
connection | connected · not_connected · not_verified |
zone | Qual zona você enviou e em qual vamos publicar. Abaixo |
blockers | O que falta no objeto para poder publicar |
pendingAtPublishTime | O que falta para publicar, mas não é do objeto (plano, filial, zona mapeada) |
Valores de status:
| Valor | Significa |
|---|---|
fields_complete | O objeto tem tudo o que esse portal precisa |
missing_data | Falta um dado. Veja blockers — há algo que você pode resolver |
not_supported | O portal não suporta algo deste imóvel. Você não resolve enviando mais dados |
coming_soon | A integração ainda não está habilitada neste endpoint |
Alguns portais não conseguem montar o anúncio até terem a sua configuração: o Zonaprop precisa do plano e
dos dados da filial para montar o anúncio. Nesses casos o portal aparece com o seu estado e os seus
pendingAtPublishTime, mas sem o mapeamento — não porque o seu objeto esteja errado, mas porque
ainda falta o dado de conta com o qual ele é construído.
Os blockers que vêm de publication trazem também um exemplo concreto de como resolvê-los,
junto à mensagem: se espera number · ejemplo: "publication": { "api": { "argenprop": { "advertiserId": 99999 } } }. Veja A chave publication.
Cada blocker traz:
{ "field": "price",
"kind": "missing",
"message": "`price` es obligatorio en el objeto de Mapaprop y no vino…",
"youCanFixIt": true }
youCanFixIt responde à única pergunta que importa sobre um blocker: eu resolvo isto enviando
mais dados, ou é uma limitação do portal? Se for true, envie o dado. Se for false, esse portal
não admite o que você está pedindo e não há JSON que resolva.
blockers e pendingAtPublishTime são coisas diferentes de propósito. Um objeto perfeito ao qual
só falta escolher o plano não é um objeto incompleto: é uma publicação sem configurar. Por isso
pendingAtPublishTime não afeta o status.
zone — em qual zona vamos publicar
Cada portal tem o seu próprio mapa de zonas, e nós mantemos a tradução entre a sua zona da Mapaprop
e a desse portal. zone mostra as duas pontas:
{ "sent": { "code": "1-2-189-973", "level": 3 },
"publishingTo": "Mar del Plata",
"status": "mapped" }
| Campo | O que diz |
|---|---|
sent.code | A zona que você enviou, tal como a montamos a partir dos seus zone0…zone3 |
sent.level | Até que nível esse código chega: 2 é o município inteiro, 3 desce até a localidade |
sent.name | O nome da sua zona, se você enviou a descrição do nível correspondente |
publishingTo | O nome da zona do portal onde o seu anúncio vai aparecer |
status | mapped · not_mapped · not_sent · not_verified |
Os estados:
| Valor | Significa |
|---|---|
mapped | Resolvemos a zona. publishingTo diz onde o anúncio vai aparecer |
not_mapped | A sua zona é válida, mas ainda não a temos mapeada para esse portal. Vem com um message explicando o que fazer |
not_sent | Você não enviou a zona no objeto |
not_verified | Não chegamos a consultar o mapeamento, então não afirmamos nada |
Olhe o publishingTo mesmo quando o estado for mapped. É o nome público da zona do portal:
se você enviou uma zona e ali aparece outra, o anúncio vai sair nesse outro lugar. Escreva para
nós e corrigimos — você é o único que pode perceber, porque é quem conhece o imóvel.
Um 0 no final do código não significa que falta um nível: 1-2-201-0 é o município inteiro,
e é um destino de publicação válido por si só. Por isso o level conta até o último número
diferente de zero.
summary
{ "summary": { "complete": 3, "of": 4 } }
Quantos portais têm os obrigatórios completos, sobre o total avaliado.
Os campos obrigatórios da Mapaprop prevalecem sobre os do portal
Esta é a coisa mais importante de entender sobre o endpoint.
A Mapaprop tem o seu próprio contrato de campos obrigatórios, e ele não depende do que cada portal
pede. Se faltar um desses campos, nenhum portal fica em fields_complete — mesmo que esse
portal em particular não o exija.
Exemplo: o Argenprop não exige o preço para montar o seu anúncio. Ainda assim, se você não enviar
price:
{
"object": {
"valid": false,
"contract": [ { "field": "price", "rule": "required", "detail": "" } ]
},
"portals": {
"argenprop": {
"status": "missing_data",
"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 }
}
A lista completa de campos obrigatórios está em O objeto JSON do imóvel.
Apenas a ausência de um obrigatório bloqueia. Um campo presente mas com um formato incorreto
aparece em object.contract e informa sem bloquear — para que você possa ir corrigindo sem que
o endpoint se torne inutilizável. Verifique sempre object.contract, não apenas o summary.
Não é preciso ter o portal conectado
O campo connection diz se a conta desse portal está conectada, mas não condiciona nada: o
objeto é mapeado do mesmo jeito e os blockers são calculados do mesmo jeito.
| Valor | Significa |
|---|---|
connected | A conta está conectada |
not_connected | Não há conta conectada para esse portal |
not_verified | Não foi possível verificar o estado da conexão |
É um dado ao lado, e continua importando: um objeto impecável não é publicado se a conta não estiver conectada. Mas para aperfeiçoar o seu objeto você não precisa ter nenhuma.
Erros
| Código | Quando |
|---|---|
400 | Falta o body, não é JSON válido, falta canonical/property, ou você pediu um portal que não existe. ⚠️ O verify NÃO devolve 400 por não ter cliente declarado — isso é do cadastro; aqui se simula com um placeholder |
403 | O token não tem o scope property-api-verify |
{ "error": "Portales desconocidos: idealista. Válidos: argenprop, zonaprop, cabaprop, mercadolibre, mapaprop" }
MercadoLibre
Sai sempre como coming_soon. A integração existe mas ainda não está habilitada neste endpoint, e
preferimos não mostrar um mapeamento sem verificar: você o tomaria por bom.
Como usá-lo
- Envie o seu objeto exatamente como você o tem hoje.
- Olhe primeiro
object.valideobject.contract. Se faltar um obrigatório, resolva isso — ele está bloqueando todos os portais ao mesmo tempo. - Olhe
object.conflicts. Se aparecer algo, o seuattributese os seus campos avulsos estão se contradizendo, eattributesganha. - Portal por portal, resolva os
blockerscomyouCanFixIt: true. - Os
youCanFixIt: falsevocê não resolve: são limites do portal. - Repita. Nada é criado, então teste quantas vezes precisar.
Precisa de ajuda? Entre em contato com o Suporte técnico da Mapaprop