Módulo 06: Leads & Clientes — API
Status: Rascunho Inicial Regras de negócio: ver
regras-negocio/06_leads_clientes.mdDomínio: verdominio/lead.md·dominio/cliente.md
1. Contratos de API (RESTful)
1.1 Leads
POST /api/leads
Auth: Consultor | Gestor | Admin
Body: { tipo_pessoa, nome, telefone?, email?, cpf_cnpj?, origem, anotacoes? }
Return: { id, status: "NOVO" }
GET /api/leads
Auth: Consultor | Gestor | Gerente | Admin
Query: ?status=NOVO&consultor_id=uuid&dias_inatividade=X&temperatura=QUENTE
Return: [{ id, nome, tipo_pessoa, status, temperatura, ultimo_contato_at, consultor: { id, nome } }]
GET /api/leads/{id}
Auth: Consultor (própria carteira) | Gestor (subordinados) | Admin
Return: { ...atributos, interacoes[], tarefas_pendentes[], timeline[] }
PATCH /api/leads/{id}/status
Auth: Consultor | Gestor
Body: { status: "EM_ANDAMENTO | QUALIFICADO | PERDIDO", motivo_descarte? }
Return: 200 OK
POST /api/leads/{id}/interacao
Auth: Consultor | Gestor
Body: { tipo: "LIGACAO | WHATSAPP | EMAIL | REUNIAO", descricao, data_interacao }
Return: { id, lead_status_atualizado: bool }
POST /api/leads/{id}/converter
Auth: Consultor | Gestor
Body: { cpf_cnpj, endereco: { cep, logradouro, numero, complemento?, bairro, cidade, uf } }
Return: { cliente_id }
Errors:
422 — CPF/CNPJ inválido algoritmicamente
409 — CPF/CNPJ já existe para outro cliente no tenant
1.2 Clientes
GET /api/clientes
Auth: Consultor | Gestor | Gerente | Admin
Query: ?busca=nome_ou_cpf&consultor_id=uuid
Return: [{ id, nome, cpf_cnpj, tipo_pessoa, total_veiculos, status }]
GET /api/clientes/{id}
Auth: Consultor (própria carteira) | Gestor (subordinados) | Admin
Return: { ...atributos, veiculos[], propostas[], contratos[], timeline[] }
PUT /api/clientes/{id}
Auth: Consultor | Gestor
Body: { nome, email, telefone, endereco: { cep, logradouro, numero, complemento?, bairro, cidade, uf } }
Return: 200 OK
Nota: cpf_cnpj e tipo_pessoa são imutáveis — não aceitos no body.
1.3 Gestão de Carteira
POST /api/leads/redistribuir
Auth: Gestor | Gerente | Admin
Body: { lead_ids: [uuid], novo_consultor_id: uuid }
Return: { total_transferidos: int }
Nota: O novo_consultor_id deve pertencer ao mesmo tenant e ser subordinado ao gestor solicitante.
2. Schemas de Dados
Lead
{
"id": "uuid",
"tenant_id": "uuid",
"consultor_id": "uuid",
"tipo_pessoa": "PESSOA_FISICA | PESSOA_JURIDICA",
"nome": "string",
"razao_social": "string | null",
"telefone": "string (E.164) | null",
"email": "string | null",
"cpf_cnpj": "string | null",
"origem": "MANUAL | IMPORTACAO | FORMULARIO_WEB | INDICACAO | AUTOMACAO",
"status": "NOVO | EM_ANDAMENTO | QUALIFICADO | CONVERTIDO | PERDIDO | EXPIRADO",
"temperatura": "FRIO | MORNO | QUENTE | null",
"anotacoes": "text | null",
"motivo_descarte": "string | null",
"ultimo_contato_at": "datetime | null",
"expiracao_at": "datetime | null",
"created_at": "datetime",
"updated_at": "datetime"
}
Interação (Evento de Timeline)
{
"id": "uuid",
"lead_id": "uuid",
"cliente_id": "uuid | null",
"consultor_id": "uuid",
"tipo": "LIGACAO | WHATSAPP | EMAIL | REUNIAO | SISTEMA",
"descricao": "text",
"data_interacao": "datetime",
"created_at": "datetime"
}
Cliente
{
"id": "uuid",
"tenant_id": "uuid",
"lead_id": "uuid",
"consultor_id": "uuid",
"tipo_pessoa": "PESSOA_FISICA | PESSOA_JURIDICA",
"nome": "string",
"razao_social": "string | null",
"cpf_cnpj": "string",
"telefone": "string (E.164)",
"email": "string",
"endereco": {
"cep": "string",
"logradouro": "string",
"numero": "string",
"complemento": "string | null",
"bairro": "string",
"cidade": "string",
"uf": "string (2 chars)"
},
"status": "ATIVO | INATIVO | BLOQUEADO",
"sincronizado_erp": "boolean",
"created_at": "datetime",
"updated_at": "datetime"
}
3. Segurança e Boas Práticas
| Regra | Implementação |
|---|---|
| Silo de dados | Consultor só acessa leads/clientes da própria carteira. Gestor acessa os de seus subordinados. tenant_id validado em toda query. |
| Conversão | O endpoint POST /api/leads/{id}/converter valida CPF/CNPJ algoritmicamente antes de criar o Cliente. Em caso de inválido, retorna 422 com mensagem descritiva. |
| Imutabilidade | cpf_cnpj e tipo_pessoa do Cliente não são atualizáveis via API. O body de PUT /api/clientes/{id} deve ignorar (ou rejeitar com 400) esses campos se enviados. |
| Auditoria | Toda mudança de status do lead e toda redistribuição de carteira geram um evento do tipo SISTEMA na timeline do lead, com consultor_id do autor da ação. |