Nota de Infraestrutura: A partir da versão 0.4.1, o backend exige a presença estrita de variáveis de ambiente vitais (
GEMINI_API_KEYS,SECRET_KEY,MONGO_URI) validadas via Pydantic. O servidor recusará a inicialização se o arquivo.envestiver incorreto ou incompleto.
Padrão Global de Erros: A partir da versão 0.5.1, todos os erros da API (HTTP 400, 401, 404, 409, 429, 500) retornam um objeto JSON padronizado no formato
{"detail": "Mensagem descritiva do erro."}.
Developer Mock Mode: A API suporta um modo de testes enviando o cabeçalho
X-Mock-Mode: true. Quando presente, os serviços de produção (Gemini) são substituídos por respostas fixas de mock, e a validação de data de expiração do JWT é ignorada, permitindo simulações locais sem consumir cotas.
Esta é a referência técnica completa de todos os endpoints disponíveis no backend FastAPI (/api/v1). Todos os retornos e requisições (exceto upload de arquivos) utilizam o formato application/json.
- Autenticação e Conta (
/auth) - Onboarding Conversacional (
/onboarding) - Processamento e Extração de IA (
/process) - Gestão de Insights / Memórias (
/insights&/confirm-insights) - Regras do Usuário (
/rules)
Aviso de Segurança (JWT): A maioria dos endpoints desta API (com exceção das rotas abertas como /auth/signup e /auth/token) requerem autenticação via token JWT. Você deve incluir o cabeçalho Authorization: Bearer <seu_token> nas requisições protegidas.
Registra um novo usuário e retorna um token de acesso JWT. Fatos de perfil e regras iniciais sugeridas também são salvos. Este endpoint possui limitação de taxa (Rate Limiting) por IP.
-
Payload Esperado:
{ "email": "usuario@exemplo.com", "password": "senha_super_segura", "profile_facts": [ // Pode ser lista vazia { "key": "Nome Completo", "value": "Maria da Silva" } ], "suggested_rules": [ // Opcional "Sempre me lembre de retornos 2 dias após orçamento." ] } -
Retornos:
- 201 (Sucesso):
{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5c...", "token_type": "bearer" } - 400 (Erro - Email duplicado):
{ "detail": "Este email já está cadastrado." } - 422 (Erro - Validação):
{ "detail": [ { "loc": ["body", "email"], "msg": "value is not a valid email address", "type": "value_error.email" } ] } - 429 (Erro - Rate Limit Excedido):
{ "detail": "Rate limit exceeded: 5 per 1 minute" } - 500 (Erro Interno):
{ "detail": "Internal Server Error" }
- 201 (Sucesso):
Autentica o usuário validando a senha e retorna um token de acesso JWT.
-
Payload Esperado:
application/x-www-form-urlencodedusername: "usuario@exemplo.com"password: "senha_super_segura"
-
Retornos:
- 200 (Sucesso):
{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5c...", "token_type": "bearer" } - 401 (Erro - Credenciais inválidas):
{ "detail": "Email ou senha incorretos." } - 422 (Erro - Validação):
{ "detail": [ { "loc": ["body", "password"], "msg": "field required", "type": "value_error.missing" } ] }
- 200 (Sucesso):
Atualiza o perfil de um usuário existente e salva regras adicionais caso informadas.
-
Payload Esperado:
{ "email": "usuario@exemplo.com", "profile_facts": [ { "key": "Telefone", "value": "11999999999" } ], "suggested_rules": [] // Opcional (novas regras a serem adicionadas) } -
Retornos:
- 200 (Sucesso):
{ "message": "Profile updated successfully", "user": { "id": "65b9c1f2e1a2b3c4d5e6f7a8", "email": "usuario@exemplo.com", "profile_facts": [ { "key": "Telefone", "value": "11999999999" } ] } } - 404 (Erro - Usuário não encontrado):
{ "detail": "User not found." } - 422 (Erro - Validação):
{ "detail": [ { "loc": [ "body", "profile_facts", 0, "key" ], "msg": "field required", "type": "value_error.missing" } ] }
- 200 (Sucesso):
Solicita a recuperação de senha enviando um e-mail com um link seguro.
-
Payload Esperado:
{ "email": "usuario@exemplo.com" } -
Retornos:
- 200 (Sucesso):
{ "message": "Se o email estiver cadastrado, um link de recuperação foi enviado." }
- 200 (Sucesso):
Define uma nova senha utilizando um token de recuperação válido.
-
Payload Esperado:
{ "token": "eyJhbGciOiJIUzI1NiIs...", "new_password": "nova_senha_segura" } -
Retornos:
- 200 (Sucesso):
{ "message": "Senha redefinida com sucesso." } - 400/401 (Erro - Token inválido ou expirado):
{ "detail": "Token inválido ou expirado." }
- 200 (Sucesso):
Exclui permanentemente a conta do usuário logado e todos os dados associados (regras e insights).
- Cabeçalhos Exigidos:
Authorization: Bearer <seu_jwt_token>
- Retornos:
- 200 (Sucesso):
{ "message": "Conta e todos os dados associados foram excluídos com sucesso." } - 401 (Erro):
{ "detail": "Could not validate credentials" }
- 200 (Sucesso):
Inicia o processo de onboarding, retornando a mensagem de boas-vindas do assistente virtual. Este endpoint possui limitação de taxa (Rate Limiting) por IP.
-
Payload Esperado: Nenhum.
-
Retornos:
- 200 (Sucesso):
{ "message": "Olá! Sou a IA do InsightPop..." } - 429 (Erro - Rate Limit Excedido):
{ "detail": "Rate limit exceeded: 5 per 1 minute" } - 500 (Erro Interno):
{ "detail": "Failed to start onboarding." }
- 200 (Sucesso):
Envia o histórico do bate-papo para o Gemini analisar o perfil do usuário de forma contínua.
-
Payload Esperado:
{ "history": [ { "role": "assistant", "content": "Olá! Como posso ajudar você hoje?" }, { "role": "user", "content": "Sou arquiteto e gostaria de organizar meus projetos." } ] } -
Retornos:
- 200 (Caso 1 - Conversa continua):
{ "type": "chat", "message": "Que legal! E quais são os dados mais importantes para você?" } - 200 (Caso 2 - A decide que tem dados suficientes ou usuário encerra):
{ "type": "profile", "profile_facts": [ { "key": "Profissão", "value": "Arquiteto" } ], "suggested_rules": [ "Priorizar extração de orçamentos e prazos de projeto" ] } - 400 (Erro - Histórico vazio):
{ "detail": "Chat history cannot be empty." } - 500 (Erro Interno):
{ "detail": "Failed to process chat onboarding." }
- 200 (Caso 1 - Conversa continua):
Recebe um arquivo desestruturado, envia para a IA (Google Gemini) e retorna os dados estruturados em JSON. (Nota: Usa um algoritmo determinístico de Smart Scoring que garante alta disponibilidade alternando chaves e modelos em milissegundos). Este endpoint possui limitação de taxa (Rate Limiting) por IP.
-
Payload Esperado: Requisição do tipo
multipart/form-datacontendo um campofile(Obrigatório). Suporta.txt, arquivos.zip(exportações do WhatsApp), Imagens (.png,.jpg) ou PDFs (.pdf). -
Retornos:
- 200 (Sucesso):
{ "context": "Professional", "title": "Orçamento Cliente X", "relevant_facts": [ { "key": "Nome", "value": "João Carlos" } ], "action_triggers": [ { "description": "Enviar proposta em PDF", "status": "pending", "date": "2026-03-01" } ], "first_contact_date": "2026-02-25", "last_contact_date": "2026-02-25" } - 400 (Erro - Tipo de arquivo não suportado):
{ "detail": "Unsupported file type: application/vnd.ms-excel." } - 429 (Erro - Rate Limit Excedido):
{ "detail": "Rate limit exceeded: 2 per 1 minute" } - 500 (Erro Interno):
{ "detail": "Erro interno ao processar resposta do Gemini." }
- 200 (Sucesso):
Endpoint principal (e central) para salvar, editar ou fundir memórias. Contém lógica interna de checagem de duplicidade por identificadores (CPF, Email, Telefone) para evitar registros repetidos.
Este endpoint atende a três fluxos distintos do aplicativo dependendo dos parâmetros enviados no payload:
- Criação de Nova Memória: Não envia
consolidate_idnemremove_ids. O backend cria um novo registro (ou avisa sobre possível duplicidade seforce_createfor falso). - Edição de Memória Existente: Envia o ID da memória que está sendo editada no campo
consolidate_id. O backend sobrescreve os dados do banco de dados com os dados recebidos neste payload. - Consolidação/Mesclagem de Memórias: Envia o ID da memória "Principal" no campo
consolidate_ide uma lista de IDs das memórias secundárias no camporemove_ids. O backend sobrescreve a memória principal com os dados do payload e apaga as memórias secundárias listadas.
-
Payload Esperado:
{ "context": "Professional", "title": "Orçamento de Projeto", // Opcional "relevant_facts": [ { "key": "Cliente", "value": "João" } ], "action_triggers": [ { "description": "Ligar", "status": "pending" } ], // Obrigatório (pode ser vazio) "user_id": "65ba9c1f2e1a2b3c4d5e6f7a8", "first_contact_date": "2026-02-25", // Opcional "last_contact_date": "2026-02-25", // Opcional "force_create": false, // Opcional (Default: false) "consolidate_id": "65b9c1f2e1a2b3c4d5e6f7a8", // Opcional (ID para atualizar registro específico em casos de Edição/Consolidação) "remove_ids": ["65c1c1f2e1a2b3c4d5e6f7a8"], // Opcional (IDs para deletar após consolidação) "ignored_ids": ["65d3c1f2e1a2b3c4d5e6f7a8"] // Opcional (IDs de registros similares que o usuário escolheu NÃO mesclar) } -
Retornos:
- 201 (Sucesso - Criado/Atualizado):
{ "message": "Informações salvas como uma nova memória.", "id": "65b9c1f2e1a2b3c4d5e6f7a8", "created": true } - 201 (Caso 2 - Match Automático detectado pela IA):
{ "status": "potential_match", "message": "Encontrei uma memória similar...", "existing_record": { "id": "65b9c1f2e1a2b3c4d5e6f7a8", "title": "Cliente Antigo", "context": "Professional", "relevant_facts": [ { "key": "Cliente", "value": "João Antigo" } ], "last_contact": "2026-02-24" } } - 404 (Erro - Não encontrado):
{ "detail": "Memória não encontrada ou já foi excluída." } - 422 (Erro - Validação):
{ "detail": [ { "loc": ["body", "user_id"], "msg": "field required", "type": "value_error.missing" } ] } - 500 (Erro Interno):
{ "detail": "An error occurred during database operation: ..." }
- 201 (Sucesso - Criado/Atualizado):
Lista todas as memórias.
-
Payload Esperado: Nenhum.
-
Query Params Esperados:
user_id(String, Obrigatório): O ID do usuário dono dos insights.workspace(String, Obrigatório): Filtra por contexto ("Personal" ou "Professional").search(String, Opcional): Busca textual global que varre Títulos (title), chaves e valores dos Fatos (relevant_facts), e descrições de Tarefas (action_triggers), ignorando acentos e case-sensitive.
-
Retornos:
- 200 (Sucesso):
[ { "_id": "65b9c1f2e1a2b3c4d5e6f7a8", "context": "Personal", "title": "Exame Médico", "relevant_facts": [ { "key": "Médico", "value": "Dr. Silva" } ], "action_triggers": [ { "description": "Retornar em 30 dias", "status": "pending", "date": "2026-03-30" } ], "user_id": "65ba9c1f2e1a2b3c4d5e6f7a8", "first_contact_date": "2026-02-25", "last_contact_date": "2026-02-25" } ] - 422 (Erro - Parâmetros ausentes):
{ "detail": [ { "loc": ["query", "workspace"], "msg": "field required", "type": "value_error.missing" } ] }
- 200 (Sucesso):
Retorna a contagem total de memórias de um usuário.
- Payload Esperado: Nenhum.
- Query Params Esperados:
user_id(String, Obrigatório): O ID do usuário dono dos insights.
- Retornos:
- 200 (Sucesso):
15
- 200 (Sucesso):
Retorna os detalhes de uma memória específica pelo seu ID.
- Payload Esperado: Nenhum.
- Retornos:
- 200 (Sucesso):
{ "_id": "65b9c1f2e1a2b3c4d5e6f7a8", "context": "Personal", "title": "Exame Médico", "relevant_facts": [], "action_triggers": [], "user_id": "65ba9c1f2e1a2b3c4d5e6f7a8" } - 404 (Erro - Não encontrado):
{ "detail": "Insight not found." }
- 200 (Sucesso):
Reagenda a data de um gatilho de ação específico dentro de uma memória.
- Payload Esperado:
{ "days": 1, // Quantidade de dias para adiar "trigger_index": 0 // Posição do gatilho no array `action_triggers` } - Retornos:
- 200 (Sucesso):
{"message": "Action trigger snoozed successfully", "new_date": "2026-03-26"} - 400 (Erro - Índice inválido):
{"detail": "Invalid trigger index"} - 404 (Erro - Não encontrado):
{"detail": "Insight not found"}
- 200 (Sucesso):
Remove permanentemente um gatilho de ação específico dentro de uma memória.
- Retornos:
- 200 (Sucesso):
{"message": "Action trigger deleted successfully"} - 400 (Erro - Índice inválido):
{"detail": "Invalid trigger index"} - 404 (Erro - Não encontrado):
{"detail": "Insight not found"}
- 200 (Sucesso):
Apaga uma memória permanentemente.
- Retornos:
- 204 (Sucesso):
No Content - 404 (Erro - Não encontrado):
{ "detail": "Insight not found." }
- 204 (Sucesso):
Gera uma unificação virtual entre um registro existente no banco e novos dados vindos de uma edição ou upload recente, sem persistir nenhuma alteração.
- Payload Esperado:
{ "primary_id": "65b9c1f2e1a2b3c4d5e6f7a8", "secondary_data": { "title": "Novo Título", "relevant_facts": [ { "key": "Cargo", "value": "Gerente" } ], "action_triggers": [ { "description": "Ligar amanhã", "date": "2026-03-03" } ], "user_id": "65ba9c1f2e1a2b3c4d5e6f7a8" } } - Retornos:
- 200 (Sucesso):
{ "title": "Novo Título", "relevant_facts": [ { "key": "Cargo", "value": "Gerente" } ], "action_triggers": [ { "description": "Ligar amanhã", "date": "2026-03-03" } ], } - 404 (Erro - Registro primário não encontrado):
{ "detail": "Primary record not found." }
- 200 (Sucesso):
Lista todas as diretrizes cadastradas. Requer user_id como Query Param.
Payload Esperado: Nenhum.
- Retornos:
- 200 (Sucesso):
[ { "id": "65ba9c1f2e1a2b3c4d5e6f7a8", "name": "Ignorar Valores", "description": "Nunca extraia dinheiro", "trigger_keywords": ["R$", "preço"], "user_id": "65ba9c1f2e1a2b3c4d5e6f7a8" } ] - 422 (Erro - Parâmetros ausentes):
{ "detail": [ { "loc": ["query", "user_id"], "msg": "field required", "type": "value_error.missing" } ] }
- 200 (Sucesso):
Cria uma nova regra para a IA.
-
Payload Esperado:
{ "name": "Nova Regra", "description": "Sempre extraia datas de vencimento", "trigger_keywords": ["vencimento", "pagar"], "user_id": "65ba9c1f2e1a2b3c4d5e6f7a8" } -
Retornos:
- 201 (Sucesso):
{ "id": "65bb9c1f2e1a2b3c4d5e6f7a8", "name": "Nova Regra", "description": "Descrição detalhada do comportamento desejado", "trigger_keywords": [ "palavra1", "palavra2" ], "user_id": "id_usuario" } - 409 (Erro - Regra já existe):
{ "detail": "Another rule with this name already exists." }
- 201 (Sucesso):
Substitui completamente os dados de uma regra.
-
Payload Esperado:
{ "name": "Nome da Regra Atualizado", "description": "Nova descrição detalhada", "trigger_keywords": [ "nova_palavra" ], "user_id": "id_usuario" } -
Retorno 200 (Sucesso):
{ "id": "65bb...", "name": "Nome da Regra Atualizado", "description": "Nova descrição detalhada", "trigger_keywords": [ "nova_palavra" ], "user_id": "id_usuario" } -
Retorno 404 (Erro - Não encontrado):
{ "detail": "Rule not found." }
Apaga uma regra.
-
Payload Esperado: Nenhum.
-
Retorno 204 (Sucesso):
No Content(Corpo vazio). -
Retorno 404 (Erro - Não encontrado):
{ "detail": "Rule not found." }