Pagar por posição
GET /property-v1/properties/{paId}/publication/{portal}/positioning
PUT /property-v1/properties/{paId}/publication/{portal}/positioning
Alguns portais permitem pagar para que um anúncio apareça mais acima na listagem. O GET te dá tudo
o que é necessário para decidir quanto; o PUT executa.
É um passo separado da publicação. Um anúncio publica do mesmo jeito sem isso; o que muda é onde ele aparece.
Cada portal cobra de um jeito diferente
O campo mechanism diz o que esperar, então um mesmo código serve para todos:
| Portal | O que se paga | mechanism | spend é |
|---|---|---|---|
| Argenprop | pontos de uma assinatura mensal, que a imobiliária distribui entre seus anúncios | points | um número |
| Zonaprop | o plano do anúncio | tier | o nome de um nível |
| MercadoLibre | o tipo de publicação | tier | o nome de um nível |
| Cabaprop | — não cobra por posição | — | — |
Hoje somente o Argenprop está habilitado. Os outros recebem 501, e a mensagem distingue os
dois casos: "o portal não tem posicionamento pago" não é o mesmo que "ainda não habilitamos isso
por aqui".
O GET: o contexto para decidir
GET …/positioning?simulate=5,100&visits=1-10
| Parâmetro | O que faz | Default |
|---|---|---|
simulate | lista de valores a simular: "em que posição eu ficaria se gastasse isso?" | vazio |
visits | faixa de posições para trazer quantas visitas cada uma recebe | vazio |
simulate custa uma chamada da cota do seu cliente POR CADA VALOR, e visits custa duas. Por
isso não vêm por default: você os pede quando precisa. Até 10 valores em simulate e 25
posições em visits.
O que ele responde
{ "portal": "argenpropapi",
"mechanism": "points",
"paId": "01M5375T7YS6PC223DWC0YQPGS",
"current": { "position": 794, "byBedrooms": 310, "indexed": true },
"bounds": { "min": 0, "max": 94518 },
"balance": { "available": 10, "total": 10, "hasSubscription": true,
"asOf": "2026-10-16T21:10:00Z" },
"segment": { "propertyType": 1, "operation": 1, "locality": 2102,
"neighborhood": 20, "bedrooms": 2 },
"simulation": [ { "spend": 5, "position": 332 }, { "spend": 100, "position": 185 } ],
"visitsByPosition": [ { "position": 1, "visits": 7991 }, { "position": 2, "visits": 3673 } ],
"thresholds": [ { "position": 1, "points": 90018 }, { "position": 2, "points": 90017 } ],
"calls": 9 }
| Campo | O que é |
|---|---|
current | Onde o anúncio está hoje. indexed: false significa que o portal ainda não o indexou |
bounds | O piso e o teto do que você pode gastar neste anúncio |
balance | O que resta ao seu cliente, com a data em que lemos |
segment | Contra qual conjunto de anúncios está sendo comparado |
simulation | Uma entrada por cada valor que você pediu |
visitsByPosition | Quantas visitas cada posição recebe |
thresholds | Quantos pontos tem quem está em cada posição |
calls | Quantas chamadas da cota do seu cliente esta consulta custou |
🔴 O dado que torna tudo o resto útil
visitsByPosition cruzado com simulation diz quantas visitas cada ponto compra:
posição 1 → 7991 visitas com 5 pontos → posição 332
posição 2 → 3673 visitas com 100 pontos → posição 185
A posição 2 recebe menos da metade do que a 1. E a curva não é linear: os primeiros 5 pontos moveram 462 posições, os 5 seguintes moveram 22.
🔴 O que não conseguimos descobrir, nós dizemos
Um bloco que não pôde ser lido não vem como null: não vem, e o seu motivo está em
unavailable.
{ "current": { "position": 794, "indexed": true },
"balance": { "available": 10, "asOf": "…" },
"unavailable": [
{ "block": "simulation", "reason": "no_indexado" },
{ "block": "visitsByPosition", "reason": "no_indexado" } ] }
A diferença importa: um campo que existe e diz null significaria "o portal diz que não há nada".
Um campo ausente com o seu motivo significa "não conseguimos descobrir", que é o que aconteceu.
reason | O que aconteceu | O que fazer |
|---|---|---|
no_indexado | o anúncio foi publicado há muito pouco tempo e o portal ainda não o indexou | esperar e pedir de novo. Não é um erro |
segmento_sin_datos_suficientes | o mercado dessa propriedade é muito pequeno para o portal ter estatísticas | nada: não há números honestos a dar |
segmento_incompleto | falta a localização da propriedade | completar a zona e publicar de novo |
| um código do portal | o portal rejeitou essa leitura | leia-o: é o mesmo tipo de código da publicação |
current e o PUT continuam funcionando mesmo que falte todo o resto. As estatísticas e a
simulação vêm de uma parte do portal que pode não estar disponível; publicar, consultar a sua
posição e atribuir não dependem dela.
Se o segmento foi ampliado, nós dizemos
Quando o segmento da sua propriedade tem poucos anúncios, o portal compara contra um mais amplo. Se isso acontecer, nós declaramos:
{ "segment": { "propertyType": 1, "operation": 1, "locality": 2102,
"neighborhood": 20, "bedrooms": null },
"segmentWidened": ["bedrooms"] }
Rotule o dado com o segmento que voltou, não com o que você pediu. Uma curva de "Palermo, qualquer quantidade de dormitórios" não é a mesma que uma de "Palermo, 2 dormitórios".
O PUT: atribuir
{ "spend": 50 }
{ "portal": "argenpropapi", "mechanism": "points",
"paId": "01M5375T7YS6PC223DWC0YQPGS",
"spend": 50, "position": 185, "calls": 3 }
position é a posição REAL que lemos, não a que a simulação prometia: nós a consultamos depois de
atribuir.
Mas o portal demora para recalculá-la. Medido: atribuindo 5 pontos, a simulação dava a posição
463 e a leitura imediata continuava devolvendo a anterior. Não é um erro e não significa que não
foi aplicado — os pontos já foram descontados do saldo. Se você quiser mostrar o efeito, peça o
GET de novo mais tarde; se quiser mostrar na hora, use o número da simulação e diga que é uma
estimativa.
spend: 0 é válido — significa "pare de pagar". Por isso não há um DELETE aqui: dar baixa
na publicação é outra coisa.
Se o portal ainda não reindexou, position não vem e nós dizemos:
{ "spend": 50, "positionUnavailable": "el portal todavía no reindexó el aviso" }
Não validamos o seu spend contra o max que lemos. Esse número vem de uma leitura que pode
estar velha, e rejeitar você por isso seria a nossa cópia decidindo em lugar do portal. O portal é a
autoridade sobre o que aceita: se ele rejeitar, devolvemos o motivo dele.
Erros
| Código | O que aconteceu |
|---|---|
400 | Um parâmetro mal formado. É validado antes de chamar o portal, então não gasta cota |
409 portal_not_connected | Essa conta não está conectada ao portal |
409 no_publicado | A propriedade não está publicada ali: não há posição a consultar |
404 | Essa propriedade não está no seu inventário |
501 | Esse portal não tem posicionamento pago habilitado aqui |
502 portal_rechazo | O portal rejeitou a atribuição. reason traz o código dele |
Relacionado
- Publicar em um portal — isto é um passo posterior
- Consultar o estado no portal — "está publicado?", que é outra pergunta
- Os estados da propriedade — reservada, vendida, alugada
- A cota do seu cliente — como é gasta