Este é o webservice principal do modo Full Stack. Recebe a mensagem do visitante, orquestra internamente a IA, a busca semântica no inventário do cliente e monta a resposta pronta para exibir. Salva a mensagem do visitante e a resposta da IA na conversa (não é preciso chamar outro endpoint para persisti-las).
Este endpoint consome tokens de IA da conta do cliente (customer_ai_config). Antes de chamá-lo você pode conferir o saldo disponível com GET /api/action/mapaprop-chat-ai-v1/validate.
| Informação do recurso | |
|---|---|
| Autenticação | Obrigatória (Token de API, Bearer) |
| Scope | mapaprop-chat-ai |
| HTTP Method | POST |
| Response | JSON |
| Version | 1 |
URL do recurso
https://mapaprop.app/api/action/mapaprop-chat-ai-v1/chat
Parâmetros
O corpo da requisição é um JSON. customerId e websiteId não são enviados: são derivados do token de autenticação.
| Key | Type | Required | Descrição |
|---|---|---|---|
| message | string | sim | A mensagem do visitante. |
| questionId | int | não | O ID da conversa a continuar. Se for omitido, uma conversa nova é criada e o questionId atribuído vem na resposta (campo questionId). Reenvie-o em cada turno seguinte. Você também pode obtê-lo de uma chamada anterior a POST /init. |
| leadName | string | não | Nome do visitante. Default Visitante. Se a conversa já tem um contato associado e não for enviado, o existente é mantido. |
| leadEmail | string | não | Email do visitante. Se for enviado e a conversa ainda não tiver contato associado, um contato é criado ou vinculado no CRM do cliente. |
| leadPhone | string | não | Telefone do visitante. |
| sessionId | string | não | Identificador de sessão do visitante (para rastreabilidade). Se não for enviado, um UUID é gerado automaticamente. |
| mode | string | não | chat (default), search ou semantic. Ver "Modo de busca" mais abaixo. |
| propertyIds | array de objetos {id: int} | não | IDs de imóveis pré-filtrados (por exemplo, obtidos de uma busca anterior pela sua conta). O modelo decide se a mensagem é uma consulta factual ("qual é o mais caro?") ou semântica ("qual tem piscina?") sobre este conjunto. |
| useVectorSearch | boolean | não | Força uma busca semântica (vetorial) nos imóveis do cliente para montar o contexto da resposta. É ativada automaticamente se for enviado propertyIds ou mode=semantic. |
| searchCriteria | object | não | Filtro de busca clássico (operation, type, zone, priceMin, priceMax, currency) usado apenas quando mode=search e não foi enviado propertyIds. Modo legacy: recomenda-se propertyIds ou useVectorSearch. |
| propertyActive | object {propertyId: int, ...} | não | Indica que a conversa é sobre UM imóvel específico (o visitante está vendo sua ficha). Tem prioridade sobre qualquer outro modo de busca. |
| searchContext | object | não | Contexto do fluxo guiado (operação / tipo / zona já escolhidos pelo visitante por meio de botões). Uso avançado, reservado para reproduzir o fluxo do widget oficial. |
| customerSearch | object | não | Dados de buscas/favoritos/consultas anteriores do visitante, usados para enriquecer o contato criado no CRM. Uso avançado. |
| sourceUrl | string | não | URL da página onde o visitante está conversando. É salva na conversa. |
Modo de busca
- Se você enviar
propertyIds, a IA responde com base nesse conjunto (com re-ranking semântico se você também enviaruseVectorSearch=true). - Se você enviar
useVectorSearch=true(oumode=semantic) sempropertyIds, a busca semântica é feita em todo o inventário do cliente. - Se você enviar
propertyActive, a resposta é focada nesse único imóvel (tem prioridade sobre tudo o mais). - Sem nenhum dos anteriores, é uma conversa livre (
chatsem contexto de busca).
Código de exemplo
POST /api/action/mapaprop-chat-ai-v1/chat HTTP/1.1
Host: mapaprop.app
Content-Type: application/json
Authorization: Bearer {access_token}
{
"message": "¿Tenés departamentos de 2 ambientes en Palermo?",
"questionId": 481203,
"leadName": "Juan Pérez",
"leadEmail": "juan@example.com",
"sessionId": "b6d1c6b0-2f2a-4e2e-9a4a-8e0a2a2f2a11",
"useVectorSearch": true
}
Resposta
A resposta inclui o questionId da conversa (o atribuído se era nova, ou o que você enviou). Salve-o e reenvie-o em cada turno seguinte para manter o fio da conversa. Também retorna o consumo de tokens do período (totalTokensUsed / tokensRemaining).
| Objeto | Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| Response | response | string | sim | O texto da resposta da IA, pronto para exibir. |
| questionId | int | sim | ID da conversa (o atribuído se era nova, ou o que você enviou). Reenvie-o no próximo turno. | |
| action | string | não | Ação sugerida pelo modelo. Valores possíveis: greeting, show_properties, confirm_search, request_info, contact. Pode vir vazio. | |
| success | boolean | sim | false quando o turno não pôde ser processado (ver "Erros controlados" mais abaixo). | |
| propertyIds | array de int | não | IDs dos imóveis referenciados nesta resposta (presente somente em modo busca). | |
| buttons | array de objetos | não | Botões sugeridos para o visitante (presente somente em alguns fluxos). | |
| allPropertyIds | array de int | não | Todos os IDs do resultado de busca (antes de recortar para os exibidos). Somente modo busca. | |
| hasMoreResults | boolean | sim | true se houver mais resultados de busca do que os exibidos em propertyIds. | |
| focusedPropertyId | int | não | ID do imóvel em foco (modo imóvel único). | |
| focusedPropertyCode | string | não | Código do imóvel em foco. | |
| searchCriteria | object | não | Critério de busca interpretado pelo modelo (modo busca). | |
| tokensUsed | object | sim | Detalhe de tokens consumidos neste turno: {input, output, total}. | |
| totalTokensUsed | int | não | Tokens de IA consumidos pela conta no período atual (após este turno). | |
| tokensRemaining | int | não | Tokens de IA restantes no período atual. | |
| error | string | não | Presente apenas quando success == false. Ver tabela abaixo. |
Erros controlados (success: false, HTTP 200)
Esses cenários não lançam uma exceção: a resposta chega com success: false, um response em português pronto para exibir ao visitante, e um error com o motivo.
| Erro | Causa |
|---|---|
TOKEN_LIMIT_EXCEEDED | O cliente atingiu o limite mensal de tokens de IA do seu plano. |
INSUFFICIENT_TOKENS | Não restam tokens suficientes no período atual para processar esta mensagem pontual. |
CONVERSATION_LIMIT_EXCEEDED | Esta conversa (questionId) já consumiu o máximo de tokens permitido por conversa. É preciso iniciar uma conversa nova. |
USER_MESSAGE_TOO_LONG | A mensagem enviada excede o tamanho máximo permitido (~300 tokens, ~225 palavras). |
| (mensagem em espanhol, não um código curto) | Falha interna do motor de IA (provedor fora do ar, erro de parseamento, etc.). O campo error neste caso contém o mesmo texto que response, não um código curto. |
Erros de validação (a requisição é cortada, não chega success: false)
| Erro | Causa |
|---|---|
REQUIRED_INPUT — "Message is required" | Falta o campo message no body. |
Exemplo de resposta
{
"response": "Sí, tenemos 3 departamentos de 2 ambientes en Palermo. Te comparto los más relevantes.",
"questionId": 481203,
"action": "show_properties",
"success": true,
"propertyIds": [2601234, 2601987, 2602111],
"hasMoreResults": false,
"tokensUsed": {
"input": 812,
"output": 143,
"total": 955
},
"totalTokensUsed": 18420,
"tokensRemaining": 81580
}
Exemplo de erro controlado (limite de tokens do período):
{
"response": "Lo siento, se ha alcanzado el limite de uso mensual del chat. El limite se reiniciara el 2026-09-01.",
"action": "",
"success": false,
"hasMoreResults": false,
"tokensUsed": {
"input": 0,
"output": 0,
"total": 0
},
"error": "TOKEN_LIMIT_EXCEEDED"
}