API Interna

Contratos entre camadas, endpoints HTTP internos e rotas nomeadas.


1. Rotas nomeadas

Públicas

Nome Método URI
home GET /
health GET /health
auth.login.show GET /login
auth.login POST /login
auth.cadastro.show GET /cadastro
auth.cadastro POST /cadastro
auth.esqueci.show GET /esqueci-senha
auth.esqueci POST /esqueci-senha
confirmar GET /confirmar/{token}
resetar.show GET /resetar-senha/{token}
resetar POST /resetar-senha/{token}
2fa.challenge GET /2fa/desafio
2fa.verify POST /2fa/verificar
webhooks.google POST /webhooks/google
webhooks.meta.verify GET /webhooks/meta
webhooks.meta POST /webhooks/meta
integracoes.leads POST /integracoes/leads

Autenticadas

Nome Método URI
dashboard GET /dashboard
logout POST /logout
clientes.index GET /clientes
clientes.create GET /clientes/novo
clientes.store POST /clientes
clientes.show GET /clientes/{id}
clientes.edit GET /clientes/{id}/editar
clientes.update POST /clientes/{id}
clientes.destroy POST /clientes/{id}/excluir
campanhas.index GET /campanhas
campanhas.create GET /campanhas/nova
campanhas.store POST /campanhas
campanhas.show GET /campanhas/{id}
campanhas.edit GET /campanhas/{id}/editar
campanhas.update POST /campanhas/{id}
campanhas.destroy POST /campanhas/{id}/excluir
diagnosticos.index GET /diagnosticos
diagnosticos.iniciar GET /diagnosticos/campanha/{campanhaId}/novo
diagnosticos.responder POST /diagnosticos/{id}/responder
diagnosticos.concluir POST /diagnosticos/{id}/concluir
diagnosticos.continuar GET /diagnosticos/{id}/continuar
diagnosticos.show GET /diagnosticos/{id}
planejamento.index GET /planejamento
planejamento.create GET /planejamento/novo
planejamento.store POST /planejamento
planejamento.gerar POST /planejamento/do-diagnostico/{diagnosticoId}
planejamento.edit GET /planejamento/{id}/editar
planejamento.update POST /planejamento/{id}
planejamento.destroy POST /planejamento/{id}/excluir
planejamento.item.marcar POST /planejamento/{planoId}/itens/{itemId}/marcar
planejamento.show GET /planejamento/{id}
metricas.index GET /metricas
metricas.lancar GET /metricas/lancar
metricas.store POST /metricas
metricas.campanha GET /metricas/campanha/{campanhaId}
metricas.destroy POST /metricas/{id}/excluir
metricas.export GET /metricas/export.csv
metricas.import GET /metricas/importar
metricas.import.upload POST /metricas/importar/upload
metricas.import.preview POST /metricas/importar/preview
metricas.import.confirmar POST /metricas/importar/confirmar
metricas.import.cancelar POST /metricas/importar/cancelar
relatorios.index GET /relatorios
relatorios.novo GET /relatorios/novo
relatorios.store POST /relatorios
relatorios.recarregar POST /relatorios/{id}/recarregar
relatorios.destroy POST /relatorios/{id}/excluir
relatorios.show GET /relatorios/{id}
leads.index GET /leads
leads.create GET /leads/novo
leads.store POST /leads
leads.edit GET /leads/{id}/editar
leads.mover POST /leads/{id}/mover
leads.interagir POST /leads/{id}/interagir
leads.interacao.excluir POST /leads/{id}/interacoes/{iid}/excluir
leads.destroy POST /leads/{id}/excluir
leads.update POST /leads/{id}
leads.show GET /leads/{id}
leads.coluna GET /leads/coluna/{estagio}
leads.export GET /leads/export.csv
feedback.store POST /feedback
feedbacks.index GET /feedbacks
feedbacks.responder POST /feedbacks/{id}/responder
funil GET /funil
events.store POST /events
perfil.index GET /perfil
perfil.senha POST /perfil/senha
perfil.2fa GET /perfil/2fa
perfil.2fa.confirmar POST /perfil/2fa/confirmar
perfil.2fa.desativar POST /perfil/2fa/desativar
perfil.2fa.backup POST /perfil/2fa/backup-codes
admin.dashboard GET /admin
admin.alertas GET /admin/alertas
admin.webhooks GET /admin/webhooks
admin.fila GET /admin/fila

2. Contratos de services

ClienteService

listar(int $usuarioId, ?string $busca, int $page, int $perPage): array
buscar(int $id, int $usuarioId): array
criar(int $usuarioId, array $dados): array
atualizar(int $id, int $usuarioId, array $dados): array
excluir(int $id, int $usuarioId): void
resumo(int $usuarioId): array
total(int $usuarioId): int

Lançam RuntimeException com mensagem pronta para exibição.

CampanhaService

Análogo ao ClienteService, com resumo() e topPorOrcamento().

DiagnosticoService

iniciar(int $campanhaId, int $usuarioId): array
responder(int $diagnosticoId, int $usuarioId, int $perguntaId, string $valor): void
concluir(int $diagnosticoId, int $usuarioId): array
buscar(int $id, int $usuarioId): array
porCampanha(int $campanhaId, int $usuarioId): array
resumo(int $usuarioId): array
recomendacoesPorPrioridade(array $respostas): array
calcular(array $perguntas, array $respostas): array

PlanoCampanhaService

criarAPartirDoDiagnostico(int $diagnosticoId, int $usuarioId): array
criarManual(int $usuarioId, array $dados): array
atualizar(int $id, int $usuarioId, array $dados): array
excluir(int $id, int $usuarioId): void
marcarItem(int $planoId, int $itemId, int $usuarioId, bool $concluido): array
buscar(int $id, int $usuarioId): array

MetricaService

lancar(int $usuarioId, array $dados): array
excluir(int $id, int $usuarioId): void
resumoCampanha(int $campanhaId, int $usuarioId, ?string $de, ?string $ate): array
resumoUsuario(int $usuarioId, ?string $de, ?string $ate): array
serieUsuario(int $usuarioId, string $de, string $ate): array
serieCampanha(int $campanhaId, int $usuarioId, string $de, string $ate): array
topCampanhas(int $usuarioId, string $de, string $ate, string $ordem, int $limite): array

RelatorioService

gerar(int $usuarioId, array $dados): array
buscar(int $id, int $usuarioId): array
listar(int $usuarioId, array $filtros, int $page, int $perPage): array
porCliente(int $clienteId, int $usuarioId): array
resumo(int $usuarioId): array
atualizarSnapshot(int $id, int $usuarioId): array

LeadService

criar(int $usuarioId, array $dados): array
atualizar(int $id, int $usuarioId, array $dados): array
mover(int $id, int $usuarioId, string $novoEstagio, ?string $motivoPerda): array
registrarInteracao(int $leadId, int $usuarioId, string $tipo, string $descricao): array
excluir(int $id, int $usuarioId): void
pipeline(int $usuarioId, array $filtros): array
coluna(int $usuarioId, string $estagio, array $filtros, int $offset, int $limit): array
resumo(int $usuarioId): array

WebhookService

receber(string $origem, string $corpo, array $headers, ?string $ip): array

O serviço valida a assinatura configurada para a origem, evita reprocessar
eventos da mesma origem/ID que já estejam processando ou processados, persiste
o evento em webhook_eventos e enfileira ProcessarWebhookJob na fila
webhooks. O retorno contém aceito e, quando aplicável, evento_id,
duplicado ou motivo.

Integração de formulário próprio

POST /integracoes/leads é uma rota pública, sem sessão e sem CSRF, destinada
ao backend de uma landing page. A rota não recebe nem utiliza a URL da landing
page: o backend do formulário envia os dados para este endpoint.

Item Contrato
Autenticação HMAC-SHA256 do corpo HTTP bruto em X-Formulario-Signature, no formato sha256=<hex>
Anti-replay timestamp Unix no JSON, dentro de FORMULARIO_TIMESTAMP_TOLERANCE (padrão: 300 segundos)
Campos obrigatórios event_type, id, timestamp, campanha_id, nome
Campos opcionais email, telefone, utm_source, utm_medium, utm_campaign, utm_content, utm_term, gclid, fbclid, mensagem
Resposta aceita 202 com {"ok":true,"status":"accepted","evento_id":...}; o lead será processado pela fila
Resposta duplicada 200 com {"ok":true,"status":"already_accepted"}
Erros de validação 422 para corpo/JSON/campos inválidos; 401 para assinatura ausente/inválida ou timestamp expirado

O id precisa ser único por envio e serve à deduplicação. Um reenvio só retorna
200 already_accepted se o evento anterior já estiver processando ou
processado; enquanto estiver pendente, pode ser aceito e enfileirado novamente.
O job também verifica se o lead daquele formulário já existe antes de criá-lo.
campanha_id deve identificar uma campanha existente; o processamento deriva
dela o cliente e o usuário proprietários, e cria o lead com origem
formulario_proprio. O segredo FORMULARIO_SECRET deve estar configurado no
.env da plataforma e no backend da landing page, nunca no JavaScript entregue
ao navegador. Consulte
CONECTOR-FORMULARIO-PROPRIO.md para o
exemplo completo de integração e configuração.

QueueWorker

tick(?string $fila): int
work(?string $fila, ?int $maxCiclos): int

3. Eventos canônicos (EventoUsoService::EVENTOS)

auth.registro
auth.confirmacao
auth.login
cliente.criado
campanha.criada
diagnostico.iniciado
diagnostico.concluido
plano.criado
metrica.lancada
relatorio.gerado
lead.criado
lead.convertido
onboarding.passo
onboarding.completo
webhook.processado

Eventos fora dessa lista são gravados com prefixo outros. para auditoria,
mas não contam no funil canônico.