Contrato — API de Ingestão
API interna que o coletor (Python) usa para enviar imóveis ao backend (Java). Não é exposta publicamente. O contrato formal está em openapi-ingestao.yaml (fonte da verdade — API-first).
Endpoints
| Método | Rota | Uso |
|---|---|---|
POST | /internal/ingest/imoveis | Lote de imóveis do CSV (coletor principal) |
POST | /internal/ingest/imoveis/{codigo}/detalhe | Detalhe enriquecido de um imóvel (coletor de detalhe — ver ADR-0010) |
Ambos: header X-Internal-Token, Idempotency-Key: <uuid>, resposta 202 Accepted (processamento assíncrono via RabbitMQ).
Lote de imóveis (CSV)
POST /internal/ingest/imoveis
- Auth: header
X-Internal-Token(segredo compartilhado na rede interna). - Idempotência: header
Idempotency-Key: <uuid>por lote. Replay da mesma key (retry do coletor) → mesmo202com o mesmoloteId(nunca409). Conteúdo comcodigorepetido é resolvido por upsert no processamento (não gera duplicata). - Resposta:
202 Accepted(processamento assíncrono via RabbitMQ).
Exemplo de requisição
http
POST /internal/ingest/imoveis HTTP/1.1
Host: backend:8080
X-Internal-Token: ***
Idempotency-Key: 8f1c...e2
Content-Type: application/jsonjson
{
"fonte": "caixa",
"uf": "SP",
"geradoEm": "2026-07-15",
"imoveis": [
{
"codigo": "1444408501866",
"uf": "SP",
"cidade": "ADAMANTINA",
"bairro": "VILA JOAQUINA",
"endereco": "ALAMEDA PADRE ANCHIETA, N. 1159, LT 05 QD 16",
"preco": 501000.00,
"valorAvaliacao": 501000.00,
"descontoPct": 0.0,
"financiamento": false,
"descricao": "Casa, 0.00 de área total, 171.43 de área privativa, 384.00 de área do terreno.",
"modalidade": "Leilão SFI - Edital único",
"link": "https://venda-imoveis.caixa.gov.br/sistema/detalhe-imovel.asp?hdnimovel=1444408501866"
}
]
}Exemplo de resposta (202)
json
{ "loteId": "9c2...", "recebidos": 1200, "aceitos": 1187, "rejeitados": 13, "publicados": 1187 }O que o backend faz ao receber (lote CSV)
- Valida o token e o payload (Bean Validation).
- Verifica a Idempotency-Key: se já processada, retorna
202com o mesmoloteId(resposta memorizada) — retry é seguro e não reprocessa. - Grava o
coleta_bruta(lote bruto, reprocessável) — o backend é o único a escrever no banco. - Publica um evento por imóvel no RabbitMQ (ver Eventos RabbitMQ), incluindo
imovel.enriquecerpara disparar a coleta de detalhe. - Responde
202com o resumo.
Detalhe enriquecido
POST /internal/ingest/imoveis/{codigo}/detalhe
Enviado pelo coletor de detalhe (Python) após raspar detalhe-imovel.asp (ver Fonte Caixa (detalhe)). Corpo = schema DetalheImovel (valor 1º/2º leilão, datas das praças, matrícula, CEP, FGTS/financiamento, despesas, fotos, PDFs).
404se ocodigoainda não foi ingerido pelo CSV.- Ao persistir, o backend publica
imovel.enriquecido→ recálculo de custos/score. - Campos são opcionais (o parser tolera ausências);
statuspode serok|parcial|falha.
Erros
Padrão Problem Details (RFC 7807) (application/problem+json) — ver schema Problem no YAML.
Notas de implementação
- O coletor envia em lotes (ex.: 500–1000 imóveis) para eficiência.
- O parsing do CSV (encoding/linhas/
trim/números BR) é responsabilidade do coletor — ver Fonte Caixa (CSV) e Collector. - O contrato é validado por testes de contrato nas duas pontas (ver Testes).