Contratos entre camadas, endpoints HTTP internos e rotas nomeadas.
| 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 |
| 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 |
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.
Análogo ao ClienteService, com resumo() e topPorOrcamento().
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
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
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
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
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
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 filawebhooks. O retorno contém aceito e, quando aplicável, evento_id,duplicado ou motivo.
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ó retorna200 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 origemformulario_proprio. O segredo FORMULARIO_SECRET deve estar configurado no.env da plataforma e no backend da landing page, nunca no JavaScript entregue
ao navegador. ConsulteCONECTOR-FORMULARIO-PROPRIO.md para o
exemplo completo de integração e configuração.
tick(?string $fila): int
work(?string $fila, ?int $maxCiclos): int
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.