# ImobyFlow API — referência completa (1.0.0)
Base: https://api.imobyflow.com.br/v1
Autenticação: `Authorization: Bearer imob_live_…` — só no cabeçalho, nunca na URL.
Língua: `Accept-Language: pt-BR` ou `en`.
## Convenções
- Acrescentar não quebra: campos, eventos, rotas e valores novos podem chegar a qualquer momento. O seu sistema deve tolerar campo que ele não conhece.
- O que quebra uma integração existente sai numa versão nova (`/v2`). A versão anterior continua funcionando por pelo menos 12 meses depois do aviso, publicado aqui e mandado por e-mail ao dono da conta.
- Os valores de código (`VENDA`, `ACTIVE`, os subtipos) são os mesmos da plataforma, sem tradução no meio.
- Erros em `application/problem+json` (RFC 9457): `type`, `title`, `status`, `code`, `requestId`, `detail` e `invalidParams` (todos os problemas de uma vez).
- Listas: `limit` e `cursor`; siga o `nextCursor` até ele vir nulo.
- Escrita: campo ausente não apaga; `null` limpa; campo desconhecido é erro 400; nada mudou = `UNCHANGED`, sem escrita.
- `?dryRun=true` valida e diz o que aconteceria, sem gravar. `Idempotency-Key` (até 100 caracteres) torna a re-tentativa segura por 24 h.
## Conta
A conta dona da chave: plano, cota de imóveis, permissões da chave, limites e o uso do mês.
### GET /me — Quem sou eu
A primeira chamada de toda integração: confirma que a chave vale e mostra a conta, as permissões desta chave, os limites e o uso do mês.
- Permissão: qualquer chave válida
Resposta 200:
- `data` (Me): Conta.
Erros: só os comuns
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/me' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
## Listas de valores
Os valores aceitos em cada campo de código: tipos de imóvel, finalidades, status, etapas, permissões e eventos. São os MESMOS valores do banco — não existe tradução no meio.
### GET /reference/property-types — Tipos de imóvel
As categorias e os subtipos. É o subtipo que vai no campo `type`.
- Permissão: qualquer chave válida
Resposta 200:
- `data` (array): A lista.
Erros: só os comuns
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/reference/property-types' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /reference/purposes — Finalidades
Venda e locação.
- Permissão: qualquer chave válida
Resposta 200:
- `data` (array): A lista.
Erros: só os comuns
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/reference/purposes' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /reference/property-statuses — Status do imóvel
Os status que o imóvel pode ter.
- Permissão: qualquer chave válida
Resposta 200:
- `data` (array): A lista.
Erros: só os comuns
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/reference/property-statuses' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /reference/lead-statuses — Etapas do cliente
As etapas do atendimento.
- Permissão: qualquer chave válida
Resposta 200:
- `data` (array): A lista.
Erros: só os comuns
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/reference/lead-statuses' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /reference/partnership-statuses — Etapas da parceria
As etapas da parceria.
- Permissão: qualquer chave válida
Resposta 200:
- `data` (array): A lista.
Erros: só os comuns
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/reference/partnership-statuses' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /reference/construction-stages — Estágios da obra
Os estágios de um lançamento.
- Permissão: qualquer chave válida
Resposta 200:
- `data` (array): A lista.
Erros: só os comuns
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/reference/construction-stages' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /reference/scopes — Permissões
As permissões que uma chave pode ter.
- Permissão: qualquer chave válida
Resposta 200:
- `data` (array): A lista.
Erros: só os comuns
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/reference/scopes' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /reference/event-types — Tipos de evento
Os eventos, com a permissão de leitura que dá acesso a cada um.
- Permissão: qualquer chave válida
Resposta 200:
- `data` (array): A lista.
Erros: só os comuns
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/reference/event-types' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
## Cidades e bairros
O catálogo de localização: cidade pelo código do IBGE e bairro pelo identificador do catálogo. Bairro é fechado contra o catálogo — é por ele que o imóvel entra nas recomendações.
### GET /geo/cities — Cidades
As cidades do catálogo, com o código do IBGE.
- Permissão: qualquer chave válida
- `uf`: Só as de um estado (2 letras).
- `q`: Parte do nome (sem acento conta igual).
- `limit`: Itens por página: de 1 a 1000 (padrão 100).
- `cursor`: O `nextCursor` da página anterior. A lista acabou quando ele vem nulo. Ele vale só para esta rota e esta conta.
Resposta 200:
- `data` (array): As cidades.
- `nextCursor` (string; nullable): Próxima página.
- `total` (integer): Total no filtro.
Erros: `invalid_param`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/geo/cities' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /geo/cities/{cityId}/neighborhoods — Bairros de uma cidade
Os bairros do catálogo. O `neighborhoodSlug` daqui é o que garante que o imóvel entra nas recomendações.
- Permissão: qualquer chave válida
- `cityId`: Código do IBGE (7 dígitos).
- `limit`: Itens por página: de 1 a 1000 (padrão 100).
- `cursor`: O `nextCursor` da página anterior. A lista acabou quando ele vem nulo. Ele vale só para esta rota e esta conta.
Resposta 200:
- `data` (array): Os bairros.
- `nextCursor` (string; nullable): Próxima página.
- `total` (integer): Total.
Erros: `invalid_param`, `not_found`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/geo/cities/4106902/neighborhoods' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
## Imóveis
A carteira da conta: ler, sincronizar pelo código do seu sistema, mudar status, confirmar disponibilidade, enviar fotos por endereço e mandar para a lixeira.
### GET /properties — Listar a carteira
A carteira da conta, mais recentes antes, com filtros. Para sincronizar, use `updatedSince` — ou os eventos.
- Permissão: `properties:read`
- `limit`: Itens por página: de 1 a 100 (padrão 50).
- `cursor`: O `nextCursor` da página anterior. A lista acabou quando ele vem nulo. Ele vale só para esta rota e esta conta.
- `status`: Status (`DELETED` = lixeira).
- `purpose`: Finalidade.
- `type`: Subtipo.
- `citySlug`: Identificador da cidade no catálogo.
- `updatedSince`: Só o que mudou desde esta data/hora (ISO 8601, UTC).
- `radar`: `pending` = só quem tem pendência para as recomendações; `ready` = só quem está pronto.
Resposta 200:
- `data` (array): Os imóveis.
- `nextCursor` (string; nullable): Cursor da próxima página (nulo = acabou).
Erros: `invalid_param`, `invalid_cursor`, `upstream_timeout`, `upstream_busy`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/properties' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /properties/by-ref/{ref} — Um imóvel pelo seu código
O imóvel pelo código do seu sistema (`externalRef`).
- Permissão: `properties:read`
- `ref`: O código do imóvel no seu sistema (até 80 caracteres; codifique espaço e `/`).
Resposta 200:
- `data` (Property): O imóvel.
Erros: `not_found`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/properties/by-ref/AP1234' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /properties/{propertyId} — Um imóvel
O imóvel, com a situação nas recomendações, na análise e na confirmação.
- Permissão: `properties:read`
- `propertyId`: Id do imóvel (`prop-…`).
Resposta 200:
- `data` (Property): O imóvel.
Erros: `not_found`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/properties/prop-3f9a1c2b7d4e' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /feed — Estado da sincronização do feed
Como terminou a última sincronização do link do CRM e se há outra agendada — para conferir o resultado depois de um `POST /v1/feed/sync`. Nunca traz o link nem o token.
- Permissão: `properties:read`
Resposta 200:
- `data` (FeedSync): O estado.
Erros: só os comuns
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/feed' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### POST /feed/sync — Sincronizar o feed agora
Avise depois de mudar a carteira no CRM: a ImobyFlow busca o MESMO link do feed, pela mesma sincronização de 6 em 6 horas — só o que mudou é gravado. A primeira chamada de cada janela de 10 minutos sincroniza na hora; as seguintes deixam UMA sincronização agendada para o fim da janela, então nenhuma alteração espera as 6 horas e chamar a cada mudança não sobrecarrega nada. Acompanhe por `GET /v1/feed` ou pelos eventos dos imóveis.
- Permissão: `properties:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
Resposta 202 (200 quando já havia uma agendada (`ALREADY_SCHEDULED`) e no ensaio.):
- `data` (FeedSync): O estado.
- `result` (FeedSyncResult): O desfecho.
Erros: `feed_not_configured`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X POST 'https://api.imobyflow.com.br/v1/feed/sync?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)"
```
### PUT /properties/by-ref/{ref} — Criar ou atualizar pelo seu código
O caminho natural de sincronização: cria o imóvel se o código for novo (201) ou atualiza o que existe (200). Campo ausente não apaga; nada mudou = `UNCHANGED`, sem escrita. A edição feita na tela vence e volta em `result.conflicts`.
- Permissão: `properties:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
- `ref`: O código do imóvel no seu sistema (até 80 caracteres; codifique espaço e `/`).
Corpo:
- `externalRef` (string): O código do imóvel no seu sistema (só no POST; no PUT ele vai no caminho).
- `title` (string): Título. Marcação HTML é removida.
- `description` (string): Descrição. ` ` e `
` viram quebra de linha; o resto da marcação sai.
- `type` (string; APARTAMENTO | CASA_RUA | CASA_CONDOMINIO | CASA_VILA | STUDIO | FLAT | COBERTURA | SALA_COMERCIAL | LOJA_PONTO | GALPAO | PREDIO | TERRENO_RUA | TERRENO_CONDOMINIO | CHACARA_SITIO | FAZENDA): Subtipo.
- `purposes` (array): Finalidades.
- `salePrice` (number; nullable): Preço de venda, em reais. Obrigatório com `VENDA`.
- `rentPrice` (number; nullable): Aluguel, em reais. Obrigatório com `LOCACAO`.
- `address` (AddressInput): Endereço.
- `bedrooms` (integer; nullable): Quartos.
- `suites` (integer; nullable): Suítes.
- `bathrooms` (integer; nullable): Banheiros.
- `parkingSpots` (integer; nullable): Vagas.
- `area` (number; nullable): Área privativa total, em m².
- `privateArea` (number; nullable): Área coberta, em m².
- `listingUrl` (string; nullable): Endereço do anúncio no seu site (http ou https).
- `captadorName` (string; nullable): Nome do captador em texto.
- `captadorAccountId` (string; nullable): Id do corretor responsável da equipe.
- `partnershipTerms` (PartnershipTerms): Condições para parceiros.
- `photos` (array): Até 30 endereços; a 1ª é a capa. Baixadas depois da resposta (veja `photoSync`). Ausente = a galeria fica como está; lista vazia = tirar as fotos.
Resposta 200 (201 quando cria.):
- `data` (Property): O objeto como ficou.
- `result` (PropertyWriteResult): O desfecho.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `feed_sync_active`, `plan_limit_reached`, `property_in_trash`, `invalid_property`, `concurrent_write`, `upstream_timeout`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X PUT 'https://api.imobyflow.com.br/v1/properties/by-ref/AP1234?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"title": "Apartamento 3 quartos no Bigorrilho",
"type": "APARTAMENTO",
"purposes": [
"VENDA"
],
"salePrice": 890000,
"address": {
"cityId": "4106902",
"neighborhoodSlug": "bigorrilho",
"street": "Rua Padre Anchieta",
"number": "1500",
"complement": "Ap 82"
},
"bedrooms": 3,
"suites": 1,
"bathrooms": 2,
"parkingSpots": 2,
"area": 98,
"photos": [
"https://www.suaimobiliaria.com.br/fotos/AP1234/1.jpg",
"https://www.suaimobiliaria.com.br/fotos/AP1234/2.jpg"
]
}
JSON
```
### POST /properties — Cadastrar um imóvel
Cria um imóvel. O mínimo: `type`, `purposes`, o preço de cada finalidade e o endereço com a cidade. Código que já existe → 409 com o id.
- Permissão: `properties:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
Corpo:
- `externalRef` (string): O código do imóvel no seu sistema (só no POST; no PUT ele vai no caminho).
- `title` (string): Título. Marcação HTML é removida.
- `description` (string): Descrição. ` ` e `` viram quebra de linha; o resto da marcação sai.
- `type` (string; APARTAMENTO | CASA_RUA | CASA_CONDOMINIO | CASA_VILA | STUDIO | FLAT | COBERTURA | SALA_COMERCIAL | LOJA_PONTO | GALPAO | PREDIO | TERRENO_RUA | TERRENO_CONDOMINIO | CHACARA_SITIO | FAZENDA): Subtipo.
- `purposes` (array): Finalidades.
- `salePrice` (number; nullable): Preço de venda, em reais. Obrigatório com `VENDA`.
- `rentPrice` (number; nullable): Aluguel, em reais. Obrigatório com `LOCACAO`.
- `address` (AddressInput): Endereço.
- `bedrooms` (integer; nullable): Quartos.
- `suites` (integer; nullable): Suítes.
- `bathrooms` (integer; nullable): Banheiros.
- `parkingSpots` (integer; nullable): Vagas.
- `area` (number; nullable): Área privativa total, em m².
- `privateArea` (number; nullable): Área coberta, em m².
- `listingUrl` (string; nullable): Endereço do anúncio no seu site (http ou https).
- `captadorName` (string; nullable): Nome do captador em texto.
- `captadorAccountId` (string; nullable): Id do corretor responsável da equipe.
- `partnershipTerms` (PartnershipTerms): Condições para parceiros.
- `photos` (array): Até 30 endereços; a 1ª é a capa. Baixadas depois da resposta (veja `photoSync`). Ausente = a galeria fica como está; lista vazia = tirar as fotos.
Resposta 201:
- `data` (Property): O objeto como ficou.
- `result` (PropertyWriteResult): O desfecho.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `feed_sync_active`, `plan_limit_reached`, `external_ref_exists`, `invalid_property`, `concurrent_write`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X POST 'https://api.imobyflow.com.br/v1/properties?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"externalRef": "AP1234",
"title": "Apartamento 3 quartos no Bigorrilho",
"type": "APARTAMENTO",
"purposes": [
"VENDA"
],
"salePrice": 890000,
"address": {
"cityId": "4106902",
"neighborhoodSlug": "bigorrilho",
"street": "Rua Padre Anchieta",
"number": "1500",
"complement": "Ap 82"
},
"bedrooms": 3,
"suites": 1,
"bathrooms": 2,
"parkingSpots": 2,
"area": 98,
"photos": [
"https://www.suaimobiliaria.com.br/fotos/AP1234/1.jpg",
"https://www.suaimobiliaria.com.br/fotos/AP1234/2.jpg"
]
}
JSON
```
### PATCH /properties/{propertyId} — Alterar parte de um imóvel
Muda só o que vier. Para limpar um campo, mande `null`.
- Permissão: `properties:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
- `propertyId`: Id do imóvel (`prop-…`).
Corpo:
- `externalRef` (string): O código do imóvel no seu sistema (só no POST; no PUT ele vai no caminho).
- `title` (string): Título. Marcação HTML é removida.
- `description` (string): Descrição. ` ` e `` viram quebra de linha; o resto da marcação sai.
- `type` (string; APARTAMENTO | CASA_RUA | CASA_CONDOMINIO | CASA_VILA | STUDIO | FLAT | COBERTURA | SALA_COMERCIAL | LOJA_PONTO | GALPAO | PREDIO | TERRENO_RUA | TERRENO_CONDOMINIO | CHACARA_SITIO | FAZENDA): Subtipo.
- `purposes` (array): Finalidades.
- `salePrice` (number; nullable): Preço de venda, em reais. Obrigatório com `VENDA`.
- `rentPrice` (number; nullable): Aluguel, em reais. Obrigatório com `LOCACAO`.
- `address` (AddressInput): Endereço.
- `bedrooms` (integer; nullable): Quartos.
- `suites` (integer; nullable): Suítes.
- `bathrooms` (integer; nullable): Banheiros.
- `parkingSpots` (integer; nullable): Vagas.
- `area` (number; nullable): Área privativa total, em m².
- `privateArea` (number; nullable): Área coberta, em m².
- `listingUrl` (string; nullable): Endereço do anúncio no seu site (http ou https).
- `captadorName` (string; nullable): Nome do captador em texto.
- `captadorAccountId` (string; nullable): Id do corretor responsável da equipe.
- `partnershipTerms` (PartnershipTerms): Condições para parceiros.
- `photos` (array): Até 30 endereços; a 1ª é a capa. Baixadas depois da resposta (veja `photoSync`). Ausente = a galeria fica como está; lista vazia = tirar as fotos.
Resposta 200:
- `data` (Property): O objeto como ficou.
- `result` (PropertyWriteResult): O desfecho.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `not_found`, `feed_sync_active`, `property_in_trash`, `invalid_property`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X PATCH 'https://api.imobyflow.com.br/v1/properties/prop-3f9a1c2b7d4e?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"salePrice": 870000
}
JSON
```
### POST /properties/{propertyId}/status — Mudar o status
Disponível, arquivado, vendido ou alugado — a mesma função da tela: só disponível ocupa a cota do plano, e quem negocia o imóvel é avisado. Vendido não volta pelo feed.
- Permissão: `properties:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
- `propertyId`: Id do imóvel (`prop-…`).
Corpo:
- `status` (string; ACTIVE | INACTIVE | SOLD | RENTED): O novo status.
Resposta 200:
- `data` (Property): O objeto como ficou.
- `result` (PropertyWriteResult): O desfecho.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `not_found`, `plan_limit_reached`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X POST 'https://api.imobyflow.com.br/v1/properties/prop-3f9a1c2b7d4e/status?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"status": "SOLD"
}
JSON
```
### POST /properties/confirm — Confirmar disponibilidade em lote
A régua dos 60 dias tira do ar o imóvel que ninguém confirma. Mande até 200 `ids` e `refs`; confirmado há menos de 24 h não regrava (`ALREADY_CONFIRMED`).
- Permissão: `properties:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
Corpo:
- `ids` (array): Ids dos imóveis.
- `refs` (array): Códigos do seu sistema.
Resposta 200:
- `data` (array): O desfecho de cada imóvel.
- `result` (object): O resumo.
- `result.dryRun` (boolean): Ensaio.
- `result.summary` (object): Contagem por desfecho.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X POST 'https://api.imobyflow.com.br/v1/properties/confirm?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"refs": [
"AP1234",
"CA0042"
]
}
JSON
```
### DELETE /properties/{propertyId} — Mandar para a lixeira
Lixeira de 30 dias (restaurável pela tela). Trava de encolhimento: no máximo 20% da carteira (e pelo menos 10) em 24 horas — um laço no seu sistema não esvazia a carteira. Com o feed do CRM ligado, quem tira imóvel do ar é o feed.
- Permissão: `properties:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
- `propertyId`: Id do imóvel (`prop-…`).
Resposta 200:
- `data` (Property): O objeto como ficou.
- `result` (PropertyWriteResult): O desfecho.
Erros: `invalid_param`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `not_found`, `shrink_guard`, `feed_sync_active`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X DELETE 'https://api.imobyflow.com.br/v1/properties/prop-3f9a1c2b7d4e?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)"
```
## Clientes
Os clientes da conta, com o perfil de busca que liga as recomendações: ler, sincronizar pelo código do seu sistema, mover no funil, arquivar e registrar atendimentos.
### GET /leads — Listar clientes
Os clientes da conta, mais recentes antes, com filtros.
- Permissão: `leads:read`
- `limit`: Itens por página: de 1 a 100 (padrão 50).
- `cursor`: O `nextCursor` da página anterior. A lista acabou quando ele vem nulo. Ele vale só para esta rota e esta conta.
- `state`: `ACTIVE` (padrão), `ARCHIVED` ou `DELETED`.
- `status`: Etapa.
- `ownerAccountId`: Só os de um corretor.
- `updatedSince`: Só o que mudou desde esta data/hora (ISO 8601, UTC).
- `radar`: `pending` = só quem tem pendência para as recomendações; `ready` = só quem está pronto.
Resposta 200:
- `data` (array): Os clientes.
- `nextCursor` (string; nullable): Cursor da próxima página (nulo = acabou).
Erros: `invalid_param`, `invalid_cursor`, `upstream_timeout`, `upstream_busy`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/leads' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /leads/{leadId} — Um cliente
O cliente, com o perfil de busca e a situação nas recomendações.
- Permissão: `leads:read`
- `leadId`: Id do cliente (`lead-…`).
Resposta 200:
- `data` (Lead): O cliente.
Erros: `not_found`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/leads/lead-7c2e9a1b3d5f' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /leads/by-ref/{ref} — Um cliente pelo seu código
O cliente pelo código do seu sistema.
- Permissão: `leads:read`
- `ref`: O código do cliente no seu sistema (até 80 caracteres).
Resposta 200:
- `data` (Lead): O cliente.
Erros: `not_found`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/leads/by-ref/CLI-889' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### PUT /leads/by-ref/{ref} — Criar, atualizar ou vincular pelo seu código
Cria o cliente (201), atualiza (200) — ou VINCULA: o código é novo, mas a pessoa já está aqui pelo telefone ou e-mail (veio de um portal, da planilha); o código passa a apontar para ela (`LINKED`), sem um segundo cliente. Na criação, `consentGiven: true` é obrigatório.
- Permissão: `leads:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
- `ref`: O código do cliente no seu sistema (até 80 caracteres).
Corpo:
- `externalRef` (string): O código do cliente no seu sistema (só no POST).
- `name` (string): Nome. Obrigatório na criação.
- `phones` (array): Até 5 telefones. Na criação, telefone ou e-mail.
- `email` (string; nullable): E-mail.
- `status` (string; NEW | ATTENDING | PROPOSAL | WON | LOST): Etapa do atendimento.
- `notes` (string): Anotações.
- `preApproved` (boolean): Crédito pré-aprovado.
- `sharedToNetwork` (boolean): O perfil pode receber imóveis de parceiros.
- `interest` (InterestInput): Perfil de busca.
- `ownerAccountId` (string): O corretor responsável, pelo id.
- `ownerEmail` (string): O corretor responsável, pelo e-mail — é como o seu sistema o conhece. Sem responsável, vale a distribuição da imobiliária.
- `lastActivityAt` (string): A última movimentação no SEU sistema. Só anda para a frente. Mais de 60 dias atrás na criação = o cliente entra arquivado (base histórica).
- `consentGiven` (boolean): Obrigatório `true` na criação: a imobiliária declara ter a base legal para tratar o dado (Termos da API).
Resposta 200 (201 quando cria.):
- `data` (Lead): O objeto como ficou.
- `result` (LeadWriteResult): O desfecho.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `consent_required`, `lead_linked_to_other_ref`, `lead_in_trash`, `external_ref_exists`, `concurrent_write`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X PUT 'https://api.imobyflow.com.br/v1/leads/by-ref/CLI-889?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"name": "Carlos Pereira",
"phones": [
{
"number": "(41) 99999-8888",
"isWhatsApp": true
}
],
"email": "carlos@example.com",
"status": "ATTENDING",
"ownerEmail": "marina@suaimobiliaria.com.br",
"interest": {
"purposes": [
"VENDA"
],
"propertyTypes": [
"APARTAMENTO"
],
"locations": [
{
"cityId": "4106902",
"neighborhoodSlug": "bigorrilho"
}
],
"salePriceMax": 950000,
"bedrooms": 3
},
"lastActivityAt": "2026-10-02T15:00:00Z",
"consentGiven": true
}
JSON
```
### POST /leads — Cadastrar um cliente
Cria um cliente. O mínimo: `name`, um telefone ou e-mail e `consentGiven: true`. Contato que já existe → 409 com o id. Sem responsável, vale a distribuição da imobiliária.
- Permissão: `leads:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
Corpo:
- `externalRef` (string): O código do cliente no seu sistema (só no POST).
- `name` (string): Nome. Obrigatório na criação.
- `phones` (array): Até 5 telefones. Na criação, telefone ou e-mail.
- `email` (string; nullable): E-mail.
- `status` (string; NEW | ATTENDING | PROPOSAL | WON | LOST): Etapa do atendimento.
- `notes` (string): Anotações.
- `preApproved` (boolean): Crédito pré-aprovado.
- `sharedToNetwork` (boolean): O perfil pode receber imóveis de parceiros.
- `interest` (InterestInput): Perfil de busca.
- `ownerAccountId` (string): O corretor responsável, pelo id.
- `ownerEmail` (string): O corretor responsável, pelo e-mail — é como o seu sistema o conhece. Sem responsável, vale a distribuição da imobiliária.
- `lastActivityAt` (string): A última movimentação no SEU sistema. Só anda para a frente. Mais de 60 dias atrás na criação = o cliente entra arquivado (base histórica).
- `consentGiven` (boolean): Obrigatório `true` na criação: a imobiliária declara ter a base legal para tratar o dado (Termos da API).
Resposta 201:
- `data` (Lead): O objeto como ficou.
- `result` (LeadWriteResult): O desfecho.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `consent_required`, `lead_exists`, `external_ref_exists`, `concurrent_write`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X POST 'https://api.imobyflow.com.br/v1/leads?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"externalRef": "CLI-889",
"name": "Carlos Pereira",
"phones": [
{
"number": "(41) 99999-8888",
"isWhatsApp": true
}
],
"email": "carlos@example.com",
"status": "ATTENDING",
"ownerEmail": "marina@suaimobiliaria.com.br",
"interest": {
"purposes": [
"VENDA"
],
"propertyTypes": [
"APARTAMENTO"
],
"locations": [
{
"cityId": "4106902",
"neighborhoodSlug": "bigorrilho"
}
],
"salePriceMax": 950000,
"bedrooms": 3
},
"lastActivityAt": "2026-10-02T15:00:00Z",
"consentGiven": true
}
JSON
```
### PATCH /leads/{leadId} — Alterar parte de um cliente
Muda só o que vier. Mudar a etapa entra no histórico, mas não conta como movimentação — para isso mande `lastActivityAt` ou registre um atendimento.
- Permissão: `leads:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
- `leadId`: Id do cliente (`lead-…`).
Corpo:
- `externalRef` (string): O código do cliente no seu sistema (só no POST).
- `name` (string): Nome. Obrigatório na criação.
- `phones` (array): Até 5 telefones. Na criação, telefone ou e-mail.
- `email` (string; nullable): E-mail.
- `status` (string; NEW | ATTENDING | PROPOSAL | WON | LOST): Etapa do atendimento.
- `notes` (string): Anotações.
- `preApproved` (boolean): Crédito pré-aprovado.
- `sharedToNetwork` (boolean): O perfil pode receber imóveis de parceiros.
- `interest` (InterestInput): Perfil de busca.
- `ownerAccountId` (string): O corretor responsável, pelo id.
- `ownerEmail` (string): O corretor responsável, pelo e-mail — é como o seu sistema o conhece. Sem responsável, vale a distribuição da imobiliária.
- `lastActivityAt` (string): A última movimentação no SEU sistema. Só anda para a frente. Mais de 60 dias atrás na criação = o cliente entra arquivado (base histórica).
- `consentGiven` (boolean): Obrigatório `true` na criação: a imobiliária declara ter a base legal para tratar o dado (Termos da API).
Resposta 200:
- `data` (Lead): O objeto como ficou.
- `result` (LeadWriteResult): O desfecho.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `not_found`, `lead_in_trash`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X PATCH 'https://api.imobyflow.com.br/v1/leads/lead-7c2e9a1b3d5f?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"status": "PROPOSAL",
"lastActivityAt": "2026-10-02T15:00:00Z"
}
JSON
```
### POST /leads/{leadId}/state — Arquivar ou reativar
`ARCHIVED` arquiva; `ACTIVE` reativa. A mesma função da tela.
- Permissão: `leads:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
- `leadId`: Id do cliente (`lead-…`).
Corpo:
- `state` (string; ACTIVE | ARCHIVED): O estado.
Resposta 200:
- `data` (Lead): O objeto como ficou.
- `result` (LeadWriteResult): O desfecho.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `not_found`, `lead_in_trash`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X POST 'https://api.imobyflow.com.br/v1/leads/lead-7c2e9a1b3d5f/state?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"state": "ARCHIVED"
}
JSON
```
### POST /leads/{leadId}/interactions — Registrar um atendimento
Contato, visita, proposta ou anotação feitos no SEU sistema, com a data dele. Conta como movimentação (o cliente não é arquivado por inatividade).
- Permissão: `leads:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
- `leadId`: Id do cliente (`lead-…`).
Corpo:
- `type` (string; CONTACT | VISIT | PROPOSAL | NOTE): `CONTACT`, `VISIT`, `PROPOSAL` ou `NOTE`.
- `note` (string): Anotação.
- `at` (string): Quando aconteceu (padrão: agora).
Resposta 200:
- `data` (Lead): O objeto como ficou.
- `result` (LeadWriteResult): O desfecho.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `not_found`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X POST 'https://api.imobyflow.com.br/v1/leads/lead-7c2e9a1b3d5f/interactions?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"type": "VISIT",
"note": "Visitou o AP1234 com a esposa.",
"at": "2026-10-02T15:00:00Z"
}
JSON
```
### DELETE /leads/{leadId} — Mandar para a lixeira
Lixeira de 30 dias; cancela as parcerias abertas do cliente, como a tela. A mesma trava de encolhimento dos imóveis.
- Permissão: `leads:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
- `leadId`: Id do cliente (`lead-…`).
Resposta 200:
- `data` (Lead): O objeto como ficou.
- `result` (LeadWriteResult): O desfecho.
Erros: `invalid_param`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `not_found`, `shrink_guard`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X DELETE 'https://api.imobyflow.com.br/v1/leads/lead-7c2e9a1b3d5f?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)"
```
## Oportunidades (Radar)
As oportunidades que o Radar encontra entre imóveis e clientes — da própria carteira e de parceiros —, com a mesma regra de exibição do painel.
### GET /properties/{propertyId}/matches — Oportunidades de um imóvel
Os clientes que combinam com o imóvel. Só clientes da própria carteira — cliente de parceiro nunca aparece no seu imóvel.
- Permissão: `radar:read`
- `propertyId`: Id do imóvel (`prop-…`).
Resposta 200:
- `data` (array): As oportunidades.
- `nextCursor` (string; nullable): Cursor da próxima página (nulo = acabou).
Erros: `not_found`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/properties/prop-3f9a1c2b7d4e/matches' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /leads/{leadId}/matches — Oportunidades de um cliente
Os imóveis que servem ao cliente — da carteira e de parceiros.
- Permissão: `radar:read`
- `leadId`: Id do cliente (`lead-…`).
Resposta 200:
- `data` (array): As oportunidades.
- `nextCursor` (string; nullable): Cursor da próxima página (nulo = acabou).
Erros: `not_found`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/leads/lead-7c2e9a1b3d5f/matches' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /matches — Oportunidades da conta
As oportunidades, mais recentes antes. As de parceiros seguem a regra de exibição do painel: sem assinatura ativa, o parceiro fica escondido (`locked`). O nome do cliente só sai com `leads:read` na chave.
- Permissão: `radar:read`
- `limit`: Itens por página: de 1 a 100 (padrão 50).
- `cursor`: O `nextCursor` da página anterior. A lista acabou quando ele vem nulo. Ele vale só para esta rota e esta conta.
- `status`: Situação.
- `scope`: Origem.
- `ownerAccountId`: Só os de um corretor.
Resposta 200:
- `data` (array): As oportunidades.
- `nextCursor` (string; nullable): Cursor da próxima página (nulo = acabou).
Erros: `invalid_param`, `invalid_cursor`, `upstream_timeout`, `upstream_busy`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/matches' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### POST /matches/{matchId}/dismiss — Descartar oportunidade
A decisão do corretor, tomada no seu sistema. Oportunidade favoritada não se descarta.
- Permissão: `radar:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
- `matchId`: Id da oportunidade. Tem `#`: mande codificado (`%23`).
Resposta 200:
- `data` (Match): O objeto como ficou.
- `result` (MatchWriteResult): O desfecho.
Erros: `invalid_param`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `not_found`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X POST 'https://api.imobyflow.com.br/v1/matches/m%23prop-3f9a1c2b7d4e%23lead-7c2e9a1b3d5f%23L/dismiss?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)"
```
### POST /matches/{matchId}/restore — Restaurar oportunidade
Volta a oportunidade descartada para as novas.
- Permissão: `radar:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
- `matchId`: Id da oportunidade. Tem `#`: mande codificado (`%23`).
Resposta 200:
- `data` (Match): O objeto como ficou.
- `result` (MatchWriteResult): O desfecho.
Erros: `invalid_param`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `not_found`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X POST 'https://api.imobyflow.com.br/v1/matches/m%23prop-3f9a1c2b7d4e%23lead-7c2e9a1b3d5f%23L/restore?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)"
```
## Parcerias
As parcerias da equipe, com a etapa e as duas pontas. Só o lado que captou o cliente move o funil.
### GET /partnerships — Parcerias da equipe
Todas as parcerias numa resposta. O `nextCursor` existe no contrato para quando ela paginar — siga-o desde já.
- Permissão: `partnerships:read`
- `status`: Etapa.
- `updatedSince`: Só o que mudou desde esta data/hora (ISO 8601, UTC).
Resposta 200:
- `data` (array): As parcerias.
- `nextCursor` (string; nullable): Cursor da próxima página (nulo = acabou).
Erros: `invalid_param`, `upstream_timeout`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/partnerships' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /partnerships/{partnershipId} — Uma parceria
A parceria, com as duas pontas e quem pode mover o funil.
- Permissão: `partnerships:read`
- `partnershipId`: Id da parceria (`pship-…`).
Resposta 200:
- `data` (Partnership): A parceria.
Erros: `not_found`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/partnerships/pship-5b8d2f1e9a3c' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### POST /partnerships/{partnershipId}/status — Mover a etapa da parceria
Só o lado que captou o cliente move o funil (`canMoveFunnel`). A contraparte só encerra depois de pedir atualização e ficar 15 dias sem resposta — a regra da tela.
- Permissão: `partnerships:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
- `partnershipId`: Id da parceria (`pship-…`).
Corpo:
- `status` (string; PENDING | ACCEPTED | DECLINED | CANCELLED | LEAD_REGISTERED | CONTACTED | NEGOTIATING | PROPOSAL | WON | LOST): A nova etapa.
Resposta 200:
- `data` (Partnership): O objeto como ficou.
- `result` (PartnershipWriteResult): O desfecho.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `not_found`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X POST 'https://api.imobyflow.com.br/v1/partnerships/pship-5b8d2f1e9a3c/status?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"status": "PROPOSAL"
}
JSON
```
## Equipe
Quem está na equipe: nome, e-mail, papel e CRECI. É pelo e-mail que o seu sistema reconhece o corretor.
### GET /team — A equipe
Quem está na equipe, inclusive suspensos.
- Permissão: `team:read`
Resposta 200:
- `data` (array): A equipe.
- `nextCursor` (string; nullable): Cursor da próxima página (nulo = acabou).
Erros: `not_available`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/team' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
## Lançamentos
O catálogo de lançamentos da cidade: empreendimento, tipologias, tabela e estágio da obra.
### GET /launches — Lançamentos da cidade
O catálogo de lançamentos, com as tipologias.
- Permissão: `launches:read`
- `limit`: Itens por página: de 1 a 50 (padrão 20).
- `cursor`: O `nextCursor` da página anterior. A lista acabou quando ele vem nulo. Ele vale só para esta rota e esta conta.
- `citySlug`: Identificador da cidade no catálogo.
- `neighborhood`: Bairro (nome).
- `type`: Subtipo.
- `stage`: Estágio da obra.
- `priceMin`: Preço mínimo.
- `priceMax`: Preço máximo.
- `q`: Busca no nome.
Resposta 200:
- `data` (array): Os empreendimentos.
- `nextCursor` (string; nullable): Cursor da próxima página (nulo = acabou).
Erros: `invalid_param`, `invalid_cursor`, `upstream_timeout`, `upstream_busy`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/launches' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
## Captação
Os proprietários que chegam à vez da conta e o aceite, que debita o crédito e libera o contato. Aceitar exige uma permissão própria e o termo específico aceito no painel.
### GET /captacao/offers — Proprietários na vez da conta
Os proprietários na vez da conta agora, com o prazo correndo — os mesmos cards da mesa —, e o resumo (crédito, pausa, módulo valendo). Antes do aceite, contato e endereço não existem na resposta.
- Permissão: `captacao:read`
Resposta 200:
- `data` (array): Os proprietários.
- `summary` (CaptacaoSummary): O resumo da mesa.
- `nextCursor` (string; nullable): Sempre nulo hoje.
Erros: `captacao_not_active`, `not_available`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/captacao/offers' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /captacao/offers/{offerId} — Um proprietário
Na vez da conta (sem contato) ou já aceito por ela (com contato).
- Permissão: `captacao:read`
- `offerId`: Id do proprietário na mesa (`cap-…`).
Resposta 200:
- `data` (CaptacaoOffer): O proprietário.
Erros: `not_found`, `captacao_not_active`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/captacao/offers/cap-8e7d6c5b4a39' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### GET /captacao/owners — Proprietários aceitos
Os aceitos, por aba da mesa, em páginas de 10, com a contagem das três abas.
- Permissão: `captacao:read`
- `tab`: A aba (padrão `ACTIVE`).
- `cursor`: O `nextCursor` da página anterior. A lista acabou quando ele vem nulo. Ele vale só para esta rota e esta conta.
Resposta 200:
- `data` (array): Os aceitos.
- `nextCursor` (string; nullable): Próxima página.
- `total` (integer; nullable): Total na aba.
- `counts` (object; nullable): Quantos em cada aba.
Erros: `invalid_param`, `invalid_cursor`, `captacao_not_active`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/captacao/owners' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### POST /captacao/offers/{offerId}/accept — Aceitar um proprietário
O único caminho da API que gasta dinheiro: debita o crédito e libera o contato. Exige a permissão `captacao:accept` e o termo do item 13 dos Termos da API aceito pelo dono no painel. Cada aceite grava a chave, o IP e a versão do termo. Ensaio responde `WOULD_ACCEPT` com o preço; a re-tentativa do mesmo aceite, `ALREADY_ACCEPTED`, sem segundo débito.
- Permissão: `captacao:accept`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
- `offerId`: Id do proprietário na mesa (`cap-…`).
Resposta 200:
- `data` (CaptacaoOffer): O proprietário (com contato).
- `result` (CaptacaoAcceptResult): O desfecho.
Erros: `invalid_param`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `request_refused`, `not_found`, `captacao_not_active`, `captacao_terms_required`, `offer_unavailable`, `captacao_insufficient_credit`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X POST 'https://api.imobyflow.com.br/v1/captacao/offers/cap-8e7d6c5b4a39/accept?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)"
```
## Eventos
O que mudou na conta, em ordem, com 30 dias de memória — a sincronização incremental. O evento é enxuto: ids e os nomes dos campos que mudaram; o detalhe vem da leitura do recurso.
### GET /events — O que mudou
Os eventos da conta em ordem, com 30 dias de memória. Guarde o `nextCursor` e mande de volta na próxima leitura — ele sempre vem, também quando não há nada novo. Cada tipo exige também a permissão de leitura do recurso. Um evento leva de segundos a mais de um minuto para aparecer: siga o CURSOR, nunca o relógio.
- Permissão: `events:read`
- `limit`: Itens por página: de 1 a 500 (padrão 100).
- `cursor`: O `nextCursor` da página anterior. A lista acabou quando ele vem nulo. Ele vale só para esta rota e esta conta.
- `since`: Começar desta data/hora (só sem cursor).
- `types`: Só estes tipos, separados por vírgula.
Resposta 200:
- `data` (array): Os eventos, em ordem.
- `nextCursor` (string): Onde continuar (sempre vem).
- `hasMore` (boolean): Há mais para ler agora.
Erros: `invalid_param`, `invalid_cursor`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/events' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
## Webhooks
Os endereços que recebem os eventos na hora, assinados no padrão Standard Webhooks, com nova tentativa, desligamento automático, reenvio e evento de teste.
### GET /webhooks — Endereços cadastrados
Os endereços de webhook da conta.
- Permissão: `webhooks:manage`
Resposta 200:
- `data` (array): Os endereços.
Erros: só os comuns
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/webhooks' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### POST /webhooks — Cadastrar um endereço
Só HTTPS e só host público. A resposta traz o `secret` (`whsec_…`) UMA vez — guarde-o: é com ele que você confere a assinatura. Esta rota não aceita `Idempotency-Key` (a resposta guardada deixaria o segredo em texto); repetir cria outro endereço.
- Permissão: `webhooks:manage`
Corpo:
- `url` (string): O endereço, só HTTPS e público. Credencial na URL é recusada.
- `types` (array): Os tipos (ausente = todos os que a conta lê).
- `description` (string; nullable): Descrição.
Resposta 201:
- `data` (Webhook): O endereço.
- `secret` (string): O segredo, só nesta resposta.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `webhook_url_refused`, `webhook_limit_reached`
```bash
curl -X POST 'https://api.imobyflow.com.br/v1/webhooks' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"url": "https://crm.suaimobiliaria.com.br/imobyflow/eventos",
"types": [
"property.updated",
"lead.created"
],
"description": "CRM — produção"
}
JSON
```
### PATCH /webhooks/{webhookId} — Alterar um endereço
Muda o endereço, os tipos, a descrição — ou desliga e religa (religar limpa o motivo do desligamento).
- Permissão: `webhooks:manage`
- Aceita `Idempotency-Key`
- `webhookId`: Id do endereço (`wh_…`).
Corpo:
- `url` (string): O endereço.
- `types` (array): Os tipos.
- `description` (string; nullable): Descrição.
- `status` (string; ACTIVE | DISABLED): `ACTIVE` religa (limpa o motivo do desligamento) e `DISABLED` desliga.
Resposta 200:
- `data` (Webhook): O endereço.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `not_found`, `webhook_url_refused`
```bash
curl -X PATCH 'https://api.imobyflow.com.br/v1/webhooks/wh_9c8b7a6f5e4d3c2b' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"status": "ACTIVE"
}
JSON
```
### DELETE /webhooks/{webhookId} — Apagar um endereço
Para de entregar e apaga o endereço.
- Permissão: `webhooks:manage`
- Aceita `Idempotency-Key`
- `webhookId`: Id do endereço (`wh_…`).
Resposta 200:
- `data` (Webhook): O endereço apagado.
- `result` (object): O desfecho.
- `result.outcome` (string): `DELETED`.
Erros: `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `not_found`
```bash
curl -X DELETE 'https://api.imobyflow.com.br/v1/webhooks/wh_9c8b7a6f5e4d3c2b' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)"
```
### POST /webhooks/{webhookId}/rotate-secret — Trocar o segredo
Gera um segredo novo, devolvido UMA vez. O anterior segue assinando junto por 24 horas — dá tempo de trocar no seu sistema sem perder evento. Sem `Idempotency-Key`.
- Permissão: `webhooks:manage`
- `webhookId`: Id do endereço (`wh_…`).
Resposta 200:
- `data` (Webhook): O endereço.
- `secret` (string): O segredo novo.
Erros: `not_found`
```bash
curl -X POST 'https://api.imobyflow.com.br/v1/webhooks/wh_9c8b7a6f5e4d3c2b/rotate-secret' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### POST /webhooks/{webhookId}/test — Mandar um evento de teste
Entrega um `webhook.test` AGORA, assinado, e devolve o que o seu sistema respondeu.
- Permissão: `webhooks:manage`
- Aceita `Idempotency-Key`
- `webhookId`: Id do endereço (`wh_…`).
Resposta 200:
- `data` (WebhookTestResult): O resultado.
Erros: `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `not_found`
```bash
curl -X POST 'https://api.imobyflow.com.br/v1/webhooks/wh_9c8b7a6f5e4d3c2b/test' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)"
```
### GET /webhooks/{webhookId}/deliveries — Entregas de um endereço
As entregas, mais novas antes, com o status, as tentativas e o último código.
- Permissão: `webhooks:manage`
- `webhookId`: Id do endereço (`wh_…`).
- `limit`: Itens por página: de 1 a 200 (padrão 50).
- `cursor`: O `nextCursor` da página anterior. A lista acabou quando ele vem nulo. Ele vale só para esta rota e esta conta.
Resposta 200:
- `data` (array): As entregas.
- `nextCursor` (string; nullable): Cursor da próxima página (nulo = acabou).
Erros: `invalid_param`, `invalid_cursor`, `not_found`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/webhooks/wh_9c8b7a6f5e4d3c2b/deliveries' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### POST /webhooks/{webhookId}/deliveries/{deliveryId}/retry — Reenviar uma entrega
Uma nova rodada de tentativas para a mesma entrega — com o MESMO `webhook-id`, então o seu sistema reconhece a repetição. A que já está agendada responde `ALREADY_SCHEDULED`.
- Permissão: `webhooks:manage`
- Aceita `Idempotency-Key`
- `webhookId`: Id do endereço (`wh_…`).
- `deliveryId`: Id da entrega (`dlv_…`).
Resposta 200:
- `data` (Delivery): A entrega.
- `result` (object): O desfecho.
- `result.outcome` (string; SCHEDULED | ALREADY_SCHEDULED): `SCHEDULED` ou `ALREADY_SCHEDULED`.
Erros: `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`, `not_found`
```bash
curl -X POST 'https://api.imobyflow.com.br/v1/webhooks/wh_9c8b7a6f5e4d3c2b/deliveries/dlv_20261002164512000_evt_4f1c9a7e2b3d8c6a5e4f1b2c/retry' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)"
```
## Lotes
Até 500 imóveis ou clientes numa chamada, processados no ritmo da plataforma, com o desfecho de cada item.
### POST /properties/batch — Lote de imóveis
Até 500 imóveis e 4 MB numa chamada. Cada item é o PUT pelo código (`externalRef` obrigatório) — as mesmas regras, os mesmos desfechos. Item mal formado volta `REJECTED` e não barra os outros; o mesmo código duas vezes no lote é recusado. Responde 202 na hora e processa no ritmo da plataforma (4 itens por segundo): 500 itens levam de 2 a 3 minutos.
- Permissão: `properties:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
Corpo:
- `items` (array): Os itens (1 a 500).
Resposta 202:
- `data` (BatchCreated): O lote recebido.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X POST 'https://api.imobyflow.com.br/v1/properties/batch?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"items": [
{
"externalRef": "AP1234",
"title": "Apartamento 3 quartos no Bigorrilho",
"type": "APARTAMENTO",
"purposes": [
"VENDA"
],
"salePrice": 890000,
"address": {
"cityId": "4106902",
"neighborhoodSlug": "bigorrilho",
"street": "Rua Padre Anchieta",
"number": "1500",
"complement": "Ap 82"
},
"bedrooms": 3,
"suites": 1,
"bathrooms": 2,
"parkingSpots": 2,
"area": 98,
"photos": [
"https://www.suaimobiliaria.com.br/fotos/AP1234/1.jpg",
"https://www.suaimobiliaria.com.br/fotos/AP1234/2.jpg"
]
}
]
}
JSON
```
### GET /properties/batch/{batchId} — Acompanhar o lote
O status, a contagem e o desfecho de cada item, na ordem do pedido. O lote fica disponível por 7 dias.
- Permissão: `properties:read`
- `batchId`: Id do lote (`b-…`).
Resposta 200:
- `data` (Batch): O lote.
Erros: `not_found`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/properties/batch/b-4c1d9e2f7a3b8c6d' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
### POST /leads/batch — Lote de clientes
Até 500 clientes e 4 MB numa chamada. Cada item é o PUT pelo código (`externalRef` obrigatório) — as mesmas regras, os mesmos desfechos. Item mal formado volta `REJECTED` e não barra os outros; o mesmo código duas vezes no lote é recusado. Responde 202 na hora e processa no ritmo da plataforma (4 itens por segundo): 500 itens levam de 2 a 3 minutos.
- Permissão: `leads:write`
- Aceita `?dryRun=true`
- Aceita `Idempotency-Key`
Corpo:
- `items` (array): Os itens (1 a 500).
Resposta 202:
- `data` (BatchCreated): O lote recebido.
Erros: `invalid_body`, `invalid_param`, `payload_too_large`, `invalid_idempotency_key`, `idempotency_key_reused`, `idempotency_in_progress`
```bash
# Modo ensaio: nada é gravado. Tire o ?dryRun=true para gravar de verdade.
curl -X POST 'https://api.imobyflow.com.br/v1/leads/batch?dryRun=true' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR' \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"items": [
{
"externalRef": "CLI-889",
"name": "Carlos Pereira",
"phones": [
{
"number": "(41) 99999-8888",
"isWhatsApp": true
}
],
"email": "carlos@example.com",
"status": "ATTENDING",
"ownerEmail": "marina@suaimobiliaria.com.br",
"interest": {
"purposes": [
"VENDA"
],
"propertyTypes": [
"APARTAMENTO"
],
"locations": [
{
"cityId": "4106902",
"neighborhoodSlug": "bigorrilho"
}
],
"salePriceMax": 950000,
"bedrooms": 3
},
"lastActivityAt": "2026-10-02T15:00:00Z",
"consentGiven": true
}
]
}
JSON
```
### GET /leads/batch/{batchId} — Acompanhar o lote
O status, a contagem e o desfecho de cada item, na ordem do pedido. O lote fica disponível por 7 dias.
- Permissão: `leads:read`
- `batchId`: Id do lote (`b-…`).
Resposta 200:
- `data` (Batch): O lote.
Erros: `not_found`
```bash
curl -X GET 'https://api.imobyflow.com.br/v1/leads/batch/b-4c1d9e2f7a3b8c6d' \
-H "Authorization: Bearer $IMOBYFLOW_API_KEY" \
-H 'Accept-Language: pt-BR'
```
## Os objetos
### Problem
Erro no formato RFC 9457 (`application/problem+json`).
- `type` (string): Endereço da página deste erro, com a causa e o conserto.
- `title` (string): O nome do erro, na língua do `Accept-Language`.
- `status` (integer): O código HTTP.
- `code` (string): Código estável — é por ele que o seu sistema decide o que fazer.
- `requestId` (string): Id da requisição. Mande junto quando falar com o suporte.
- `detail` (string): Explicação do caso (quando houver).
- `invalidParams` (array