Vetor — Site Lead Intake Endpoint

Endpoint de captura de leads para mattosaeroportos.com.br. Aceita POST de qualquer plataforma de formulários (Webflow, WordPress, HTML puro, Typeform, etc.).

Endpoint

MétodoPathDescrição
POST/leadRegistra um novo lead

Contrato de entrada — campos aceitos

CampoTipoDescrição
nomeobrigatóriostringNome ou razão social. Mín. 2 caracteres.
emailobrigatóriostringE-mail válido. Usado para dedup e contato.
lgpd_consentobrigatórioboolean trueConsentimento explícito LGPD. Deve ser o literal true. Rejeitado se ausente ou false.
telefoneopcionalstringTelefone/WhatsApp. Formato livre, máx. 20 chars.
empresaopcionalstringNome da empresa. Máx. 100 chars.
cnpjopcionalstringCNPJ (com ou sem formatação). Usado para dedup PJ — se 14 dígitos, chave principal de dedup.
mensagemopcionalstringMensagem livre do lead. Máx. 2000 chars.
servicoopcionalstringServiço de interesse. Máx. 50 chars.
segmentoopcionalstringHint de segmento. Valores aceitos: piloto, arquiteto, construtora, condomínio de luxo, resort, hotel de luxo, hotel fazenda, vinícolas, náutica, shopping, loja de carro de luxo, empresas aéreas, empresa +10m/mês. Valor desconhecido é ignorado (não rejeitado).
utm_sourceopcionalstringUTM tracking. Máx. 100 chars cada.
utm_mediumopcionalstring
utm_campaignopcionalstring
utm_contentopcionalstring
utm_termopcionalstring
⚠️ Campos não listados acima são rejeitados com HTTP 400 — o endpoint não aceita campos desconhecidos. Configure o form para enviar exatamente esses campos.

Respostas

HTTPSignificadoBody JSON
201Lead registrado{ site_lead_id, dimensions: { origem, segmento, relacao, setor_mercado, ... } }
400Payload inválido{ error: "validation_failed", details: [...] }
409Lead já existe (dedup){ error: "already_exists", by: "email"|"cnpj" }
429Rate limit (10 req/min/IP){ error: "rate_limit", retry_after_s: 60 }
405Método não permitido{ error: "method_not_allowed" }

Exemplo de POST (curl)

curl -s -X POST http://localhost:3456/lead \
  -H 'Content-Type: application/json' \
  -d '{
    "nome": "Matheus Mattos",
    "email": "matheus@empresa.com.br",
    "telefone": "+55 11 99999-0000",
    "empresa": "Empresa Exemplo Ltda",
    "cnpj": "12.345.678/0001-95",
    "servico": "hangar",
    "mensagem": "Quero conhecer os planos para hangar privativo.",
    "segmento": "empresas aéreas",
    "lgpd_consent": true,
    "utm_source": "google",
    "utm_medium": "cpc",
    "utm_campaign": "site-2026"
  }'

Configuração Webflow

Adicione um bloco Form com campos que mapeiem para os nomes acima. No Form Settings → Action, defina a URL do endpoint (após deploy). Use um Hidden Field para lgpd_consent com valor true.

O que foi provado (localmente)

O que falta para o owner ativar em produção

  1. Deploy do servidor — subir este processo (node scripts/site-lead-intake.cjs) na VPS com as credenciais de prod em .env (as mesmas que os outros scripts usam).
  2. URL pública — apontar um domínio ou subdomínio (ex.: api.mattosaeroportos.com.br/lead) para a porta 3456 do servidor via nginx/Caddy. Ou usar um Supabase Edge Function como proxy se preferir serverless.
  3. Plataforma do form — confirmar qual é a plataforma do mattosaeroportos.com.br e configurar o form action para a URL pública acima. Para Webflow: Form Settings → Action URL. Para WordPress: plugin de forms com Custom Action. Para HTML puro: action="URL" + method="POST".
  4. CORS — se o form usa fetch/AJAX em vez de submit nativo, configurar o header Access-Control-Allow-Origin com o domínio do site (já incluído no endpoint — mudar de * para o domínio exato é boa prática em produção).
  5. HTTPS — TLS obrigatório para formulários em produção (LGPD + OWASP).
  6. Rate limit persistente — o rate limiter atual é in-memory (por processo). Se a VPS reiniciar, o contador zera. Para um rate limiter que sobrevive a restarts, usar Redis ou o próprio Supabase como backend de contagem.

Endpoint construído em 2026-08-24 · scripts/site-lead-intake.cjs