Usamos cookies essenciais para o funcionamento do site e, com seu consentimento, cookies de análise e marketing para melhorar sua experiência. Saiba mais
Documentação para desenvolvedores
Conecte seu CRM, site institucional ou sistema próprio ao Alto Vale Shopping. Publique e atualize imóveis por REST, sincronize a galeria de fotos, leia leads, visitas, lista de espera e mensagens, e receba eventos em tempo real por webhook — tudo autenticado por API Key.
A API do Alto Vale Shopping é REST/JSON e escopada por conta: uma chave enxerga e escreve apenas os imóveis do anunciante que a gerou. O escopo vem da própria chave — não existe parâmetro de owner na requisição, e um owner_id enviado no corpo é descartado pelo servidor.
Base URL
https://altovaleshopping.com/api/v1
Autenticação
X-API-Key: av_live_…
/v1/) com aviso prévio aos parceiros com chave ativa — a v1 atual continua respondendo.Abra as configurações do painel
Entre na sua conta e vá em Painel → Configurações, aba Integrações. A seção API Keys lista as chaves existentes com prefixo, escopos, limite e data do último uso.
Clique em “Nova chave”
Dê um nome interno que identifique o consumidor — “CRM Vista”, “Site institucional”, “Script de importação”. Uma chave por sistema: assim você revoga um integrador sem derrubar os outros.
Escolha os escopos
properties:read para leitura e properties:write para criar, editar, remover e mexer em fotos. Marque só o que o sistema realmente precisa — um site que apenas exibe imóveis não deve ter escrita.
Defina o rate limit
Padrão de 60 requisições por minuto, contado por chave (não por IP). Para cargas maiores, solicite o aumento ao suporte.
Copie a chave — ela aparece uma única vez
O formato é av_live_ + 32 caracteres hexadecimais. A plataforma guarda apenas o hash SHA-256: ninguém — nem o suporte — consegue recuperar o valor depois. Se perder, revogue e gere outra.
Guarde em cofre de segredos (1Password, AWS Secrets Manager, variável de ambiente do servidor). Nunca no front-end, em repositório ou em app mobile — a chave tem poder de escrita sobre o seu inventário.
Pronto. A chave já vale para a primeira chamada.
Revogar: na mesma tela, ícone de lixeira ao lado da chave. A revogação é imediata — a chamada seguinte recebe 401.
Liste os imóveis ativos da sua conta. Se voltar 200 com data e total, a autenticação está correta.
curl 'https://altovaleshopping.com/api/v1/properties?page=1&limit=20&status=ativo' \
-H "X-API-Key: av_live_SUA_CHAVE_AQUI"const API = "https://altovaleshopping.com/api/v1";
const KEY = process.env.AVS_API_KEY!; // nunca hardcode a chave
const res = await fetch(`${API}/properties?status=ativo&limit=100`, {
headers: { "X-API-Key": KEY },
});
if (!res.ok) throw new Error(`API ${res.status}: ${(await res.json()).error}`);
const { data, total, page, limit } = await res.json();
console.log(`${data.length} de ${total} imóveis`);$ch = curl_init("https://altovaleshopping.com/api/v1/properties?status=ativo");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-API-Key: " . getenv("AVS_API_KEY")]);
$body = json_decode(curl_exec($ch), true);cover_image — a primeira foto da galeria, para você montar uma listagem sem um GET por imóvel. Para o objeto completo com descrição, características e galeria inteira, use GET /properties/:id.| Escopo | Permite |
|---|---|
| properties:read | GET de lista e de imóvel único |
| properties:write | POST, PUT, PATCH, DELETE e endpoints de fotos |
| properties:all | Leitura + escrita (curinga) |
Um método de escrita com chave só de leitura devolve 403 com Insufficient scope.
Rate limit: teto por minuto por chave, padrão 60. Ao estourar, a resposta é 429 e a requisição não é processada. Em sincronizações em lote, espace as chamadas em ~1s.
Paginação: ?page= (base 1) e ?limit= (máximo 100). O total de registros vem em total.
| Método & path | O que faz |
|---|---|
| GET /properties | Lista os imóveis da conta. Filtros: status, updated_since. Cada item traz cover_image. |
| GET /properties/:id | Objeto completo + galeria de imagens. |
| POST /properties | Cria imóvel. Sem status informado, entra como rascunho. |
| PATCH /properties/:id | Atualização parcial — envie só os campos que mudaram. |
| PUT /properties/:id | Idêntico ao PATCH (campos omitidos permanecem). |
| DELETE /properties/:id | Soft delete: marca status=removido, não apaga o registro. |
| POST /properties/:id/images | Adiciona ou substitui fotos a partir de URLs públicas. |
| DELETE /properties/:id/images/:imageId | Remove uma foto da galeria e do storage. |
| GET /leads | Leads do CRM. Filtros: origin, column, updated_since. |
| GET /leads/:id | Lead completo + property_ids vinculados. |
| GET /leads/:id/interactions | Histórico do lead: notas, ligações, movimentações. |
| GET /visits | Agendamentos de visita. Filtros: status, from, to. |
| GET /waitlist | Lista de espera por perfil de imóvel. Filtro: status. |
| GET /messages | Conversas do chat. Filtros: property_id, unread, since. |
O corpo de escrita passa por uma allowlist: campos fora dela (id, owner_id, view_count, featured, valores calculados) são descartados em silêncio, sem erro. A lista completa de campos graváveis e o schema do recurso estão na referência OpenAPI.
# 1. cria (entra como rascunho)
RES=$(curl -sS -X POST "https://altovaleshopping.com/api/v1/properties" \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{
"title": "Casa 3 quartos no Centro",
"property_type": "venda",
"category": "casa",
"price": 450000,
"address_street": "Rua XV de Novembro",
"address_number": "100",
"address_neighborhood": "Centro",
"address_city": "Rio do Sul",
"address_state": "SC",
"address_zip": "89160-000",
"reference_code": "SEU-ID-EXTERNO-123"
}')
ID=$(echo "$RES" | jq -r .id)
# 2. publica
curl -sS -X PATCH "https://altovaleshopping.com/api/v1/properties/$ID" \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{"status":"ativo"}'/properties é o que você publica. Estes quatro recursos são o que o marketplace devolve para a sua conta — o outro lado da integração, para o seu CRM não depender de e-mail ou de alguém olhando o painel.
| Recurso | Conteúdo | Escopo |
|---|---|---|
| /leads | Leads do CRM com origem, urgência, coluna do funil, corretor responsável e histórico de interações. | leads:read |
| /visits | Visitas agendadas: data, horário, status, contato do visitante e corretor atribuído. | visits:read |
| /waitlist | Compradores esperando por um perfil de imóvel (tipo, região, faixa de preço). | waitlist:read |
| /messages | Conversas do chat da sua conta, com o imóvel relacionado e o marcador de lida. | messages:read |
Quem enxerga o quê
O recorte de linhas vem da chave, nunca de um parâmetro. Chave de imobiliária vê os registros dela e dos corretores vinculados; chave de corretor vinculado vê os próprios — e, em leads, só os atribuídos a ele. Mensagens são a exceção deliberada: uma chave só lê as conversas da própria conta, nunca as de um corretor, porque conversa é dele com o comprador.
curl 'https://altovaleshopping.com/api/v1/leads?updated_since=2026-08-01T00:00:00Z&limit=100' \
-H "X-API-Key: $KEY"
# {
# "data": [
# {
# "id": "uuid",
# "name": "Maria Souza",
# "email": "[email protected]",
# "phone": "47999990000",
# "origin": "visita",
# "urgency": "alta",
# "status_column_id": "col_novo",
# "source_property_id": "uuid",
# "assigned_broker_id": null,
# "created_at": "2026-08-02T13:41:07.201Z"
# }
# ],
# "total": 37, "page": 1, "limit": 100
# }POST aqui retorna 403 (não existe escopo de escrita para esses recursos no painel); se o escopo for concedido manualmente, a própria API ainda recusa com 405. Precisa escrever? Fale com o suporte.O desenho abaixo é o que recomendamos para um CRM que já tem a carteira de imóveis e quer espelhá-la no marketplace.
Carga inicial
Para cada imóvel do seu sistema: POST /properties como rascunho → POST /properties/:id/images → PATCH status=ativo. Publicar só depois das fotos evita anúncio sem imagem no ar.
Guarde o mapeamento de IDs
A API não é idempotente: cada POST cria um registro novo. Salve seu_id → id_da_plataforma no seu banco (e mande também o seu identificador em reference_code / source_url). Sem isso, um retry após timeout duplica o anúncio.
Atualizações incrementais
Mudou preço, status ou descrição no seu CRM? Um PATCH com apenas os campos alterados. Não reenvie o objeto inteiro — é mais barato e evita sobrescrever ajustes feitos no painel.
Baixa do imóvel
Vendido: PATCH status=vendido (mantém o histórico e a página). Saiu da carteira: DELETE, que faz soft delete.
Reconciliação periódica
Entre as rodadas, use GET /properties?updated_since=… para puxar só o que mudou. Uma vez por dia, faça a varredura completa paginada e compare com o seu inventário: crie o que falta, atualize divergências, remova o que saiu. É a rede de segurança para eventos perdidos.
KEY="av_live_..."
URL="https://altovaleshopping.com/api/v1"
PAGE=1
while :; do
RES=$(curl -sS "$URL/properties?page=$PAGE&limit=100" -H "X-API-Key: $KEY")
echo "$RES" | jq -r '.data[] | [.id, .reference_code, .status, .price] | @tsv'
TOTAL=$(echo "$RES" | jq -r .total)
(( PAGE * 100 >= TOTAL )) && break
PAGE=$((PAGE + 1))
sleep 1 # respeita o rate limit
doneNão há upload binário. Você envia URLs públicas e o servidor baixa, valida e re-hospeda cada imagem — o download sai do nosso lado, com o Referer correto para CDNs que bloqueiam hotlink. Até 50 URLs por requisição.
curl -X POST 'https://altovaleshopping.com/api/v1/properties/UUID/images' \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{
"source_urls": ["https://cdn.seucrm.com/1.jpg", "https://cdn.seucrm.com/2.jpg"],
"replace": true
}'Com replace: true a troca é protegida: as fotos novas entram em posições provisórias e a galeria antiga continua servindo o anúncio durante os downloads. A substituição só é confirmada se a galeria nova ficar maior que a atual — se o seu CDN falhar no meio de 30 fotos e só 2 chegarem, o anúncio permanece com as 30 e a resposta traz replaced: false com o motivo.
Uma URL é ignorada (contabilizada em skipped, sem derrubar a requisição) quando a resposta não é 2xx, o Content-Type não é de imagem, o arquivo é menor que 5 KB (pixel de tracking), tem menos de 500px nos dois eixos (logo de imobiliária) ou passa de 15 MB.
http/https para hosts públicos. Localhost, loopback, faixas privadas, CGNAT, link-local (incluindo endpoints de metadados de nuvem), IPv6 literal e domínios .internal são recusados.A API cobre a saída (você publica). Os webhooks cobrem a entrada: leads, visitas, propostas e mensagens geradas no marketplace chegam ao seu sistema em segundos, sem polling.
Cadastre a URL
Painel → Configurações → aba Integrações → Webhooks. Informe um endpoint HTTPS público e selecione os eventos.
Defina um secret
Com secret configurado, cada entrega leva o header X-Webhook-Signature — HMAC SHA-256 do corpo bruto, em hexadecimal. Valide sempre antes de processar.
Responda 2xx rápido
O timeout é de 10 segundos e fazemos 2 tentativas (a segunda 1s depois). Enfileire o processamento e responda imediatamente. O histórico de entregas com status e corpo da resposta fica visível no painel.
Eventos disponíveis
{
"event": "lead.created",
"payload": { "...": "dados do evento" },
"timestamp": "2026-08-10T12:34:56.000Z",
"delivery_id": "uuid"
}
// Headers
// X-Webhook-Event: lead.created
// X-Webhook-Delivery: uuid
// X-Webhook-Signature: <hmac-sha256-hex do corpo, se houver secret>import crypto from "node:crypto";
app.post("/webhooks/avs", express.raw({ type: "application/json" }), (req, res) => {
const expected = crypto
.createHmac("sha256", process.env.AVS_WEBHOOK_SECRET!)
.update(req.body) // corpo BRUTO, antes do JSON.parse
.digest("hex");
const received = req.header("X-Webhook-Signature") ?? "";
const ok =
received.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
if (!ok) return res.sendStatus(401);
res.sendStatus(200); // responde primeiro
enqueue(JSON.parse(req.body)); // processa depois
});delivery_id: a retentativa reenvia o mesmo id, e uma resposta lenta pode gerar entrega repetida do mesmo evento.Toda resposta de erro tem o mesmo formato: { "error": "mensagem" }.
| Código | Causa e ação |
|---|---|
| 400 | JSON inválido, título ausente ou nenhum campo gravável no corpo. Não retente sem corrigir. |
| 401 | Chave ausente, inválida ou revogada. Confira o header X-API-Key. |
| 403 | Escopo insuficiente — a chave não tem properties:write. |
| 404 | Recurso ou imóvel inexistente, ou pertencente a outra conta. |
| 405 | Método não suportado no path (ex.: PATCH sem :id). |
| 429 | Rate limit estourado. Aguarde até 60s e refaça. |
| 500 | Erro interno. Retente com backoff exponencial; se persistir, contate o suporte. |
async function callApi(path: string, init: RequestInit = {}) {
for (let attempt = 0; attempt < 3; attempt++) {
const r = await fetch(`${API}${path}`, {
...init,
headers: { "X-API-Key": KEY, "Content-Type": "application/json", ...init.headers },
});
if (r.ok) return r.json();
if (r.status === 429) { // limite: espera crescente
await sleep(1000 * (attempt + 1));
continue;
}
if (r.status >= 500) { // servidor: backoff exponencial
await sleep(500 * 2 ** attempt);
continue;
}
throw new Error(`API ${r.status}: ${(await r.json()).error}`); // 4xx: não retentar
}
throw new Error("Máximo de tentativas excedido");
}Antes de ligar a integração em produção, confirme:
A chave está em cofre/variável de ambiente, fora do repositório.
O escopo da chave é o mínimo necessário.
Existe mapeamento persistido entre o seu ID e o id da plataforma.
Retentativas tratam 429 e 5xx; 4xx não são retentados em loop.
As chamadas em lote respeitam o limite por minuto (~1s entre requisições).
Fotos são enviadas antes de publicar o imóvel (status=ativo).
O endpoint de webhook valida X-Webhook-Signature e responde 2xx em menos de 10s.
Entregas repetidas são deduplicadas por delivery_id.
Há alarme/log do seu lado para falhas de sincronização.
Dúvidas de integração, aumento de rate limit, acesso a recursos ainda não expostos ou relato de incidente: [email protected]. Inclua o prefixo da chave (nunca a chave inteira), o horário aproximado e o corpo da resposta recebida.