Guia completo: Chamada de API no bot Zenvia → HubSpot Forms API
A integração permite que o bot da Zenvia envie dados de leads capturados via WhatsApp diretamente para o HubSpot CRM da PetLove, sem middleware, sem servidor externo e sem Operations Hub.
| Critério | Fluxo A Middleware |
Fluxo B Ops Hub Direto |
Path C (Recomendado) Forms API |
|---|---|---|---|
| Precisa Ops Hub? | Não | Sim (já contratado) | Não |
| Precisa servidor? | Sim (Node.js) | Não | Não |
| Contato novo? | Cria | Ignorado (necessita tratamento via código) | Cria automaticamente |
| Autenticação? | API key | Webhook URL | Nenhuma (público) |
| Tempo de dev (full) | 46-60 dias úteis | 15-25 dias úteis | 15-20 dias úteis |
| Prazo V1 | 26/03/2026 (15 dias úteis) | 26/03/2026 (15 dias úteis) | 26/03/2026 (15 dias úteis) |
| Quem implementa? | EPIC (código) | EPIC (workflow) | Time Zenvia/PetLove (builder) + EPIC (workflow) |
knWv****************************cyBp) retorna HTTP 401 (Unauthorized) ao testar contra a API v2 da Zenvia (GET https://api.zenvia.com/v2/subscriptions). Isso significa que:https://app.zenvia.com/home/api e compartilhar com a EPIC.Passo a passo para configurar a "Chamada de API" no Construtor do Bot da Zenvia Conversion.
No Construtor do Bot, crie um novo bloco após a coleta de dados do lead. Nomeie-o como EnviarParaHubSpot ou similar.
Clique nos três pontinhos do bloco → Adicionar conteúdo → Chamada de API.
| Campo | Valor |
|---|---|
| Método | POST |
| URL | https://api.hsforms.com/submissions/v3/integration/submit/50501903/a5edb59a-d033-4905-84d4-c00cbed2403e |
No campo Cabeçalho, adicione:
Content-Type: application/json
Não é necessário nenhum token de autenticação. A Forms API é pública por design.
No campo Corpo, cole o JSON abaixo. Substitua os valores fixos pelas variáveis do bot usando a sintaxe <? $nome_variavel ?>.
Veja a Seção 5 para o JSON completo e a Seção 6 para o mapeamento de variáveis.
A resposta fica disponível em <? $resposta_api.body ?>. No bloco seguinte, você pode:
$resposta_api.code == 200, seguir fluxo normal| Parâmetro | Valor |
|---|---|
| URL completa | https://api.hsforms.com/submissions/v3/integration/submit/50501903/a5edb59a-d033-4905-84d4-c00cbed2403e |
| Portal ID | 50501903 |
| Form ID | a5edb59a-d033-4905-84d4-c00cbed2403e |
| Método | POST |
| Content-Type | application/json |
| Autenticação | Nenhuma — Forms API é pública |
| Rate Limit | 100 submissões / 10 segundos por formulário |
| Dedup | Por email — mesmo email atualiza contato existente |
| Protocolo | HTTPS (obrigatório) |
Copiar e colar no campo Corpo da Chamada de API. Substituir valores fixos por variáveis do bot.
{
"fields": [
// ---- DADOS DO CONTATO (coletados pelo bot) ----
{ "name": "email", "value": "<? $email_lead ?>" },
{ "name": "firstname", "value": "<? $primeiro_nome ?>" },
{ "name": "lastname", "value": "<? $sobrenome ?>" },
{ "name": "phone", "value": "<? $telefone ?>" },
// ---- DADOS DO PET ----
{ "name": "pet_name", "value": "<? $nome_pet ?>" },
{ "name": "pet_species", "value": "<? $especie_pet ?>" },
// ---- DADOS ZENVIA CORE ----
{ "name": "zenvia_conversation_id", "value": "<? $conversation_id ?>" },
{ "name": "zenvia_channel", "value": "whatsapp" },
{ "name": "first_message", "value": "<? $primeira_mensagem ?>" },
{ "name": "zenvia_event_id", "value": "<? $event_id ?>" },
{ "name": "zenvia_subscription_id", "value": "sub_petlove_whatsapp" },
{ "name": "zenvia_event_type", "value": "MESSAGE" },
{ "name": "zenvia_message_id", "value": "<? $message_id ?>" },
{ "name": "zenvia_direction", "value": "IN" },
{ "name": "zenvia_from", "value": "<? $telefone_lead ?>" },
{ "name": "zenvia_to", "value": "551140042500" },
{ "name": "zenvia_content_type", "value": "text" },
{ "name": "zenvia_timestamp", "value": "<? $timestamp ?>" },
{ "name": "zenvia_message_status", "value": "delivered" },
{ "name": "zenvia_whatsapp_name", "value": "<? $whatsapp_name ?>" },
{ "name": "zenvia_bot_flow_id", "value": "<? $flow_id ?>" },
{ "name": "zenvia_metadata", "value": "<? $metadata_json ?>" },
// ---- REFERRAL / CLICK-TO-WHATSAPP ADS ----
{ "name": "zenvia_referral_headline", "value": "<? $referral_headline ?>" },
{ "name": "zenvia_referral_source_type", "value": "<? $referral_type ?>" },
{ "name": "zenvia_referral_source_url", "value": "<? $referral_url ?>" },
{ "name": "zenvia_referral_ctwa_id", "value": "<? $ctwa_id ?>" },
{ "name": "zenvia_contact_id", "value": "<? $zenvia_contact_id ?>" },
{ "name": "zenvia_flow_response_data", "value": "<? $flow_response ?>" },
// ---- STATUS & ERROS ----
{ "name": "zenvia_visitor_picture", "value": "<? $visitor_picture ?>" },
{ "name": "zenvia_status_description", "value": "<? $status_desc ?>" },
{ "name": "zenvia_status_error_code", "value": "<? $error_code ?>" },
{ "name": "zenvia_status_error_reason", "value": "<? $error_reason ?>" },
{ "name": "zenvia_channel_provider", "value": "<? $channel_provider ?>" },
{ "name": "zenvia_message_payload", "value": "<? $msg_payload ?>" }
],
"context": {
"pageUri": "https://api.zenvia.io/whatsapp",
"pageName": "Zenvia WhatsApp - PetLove"
}
}
email é obrigatório. Se algum campo não estiver disponível no bot, remova a linha do JSON ou envie com valor vazio (""). Campos não reconhecidos são ignorados silenciosamente.
| # | HubSpot Property | Fonte Zenvia | Variável Bot (exemplo) | Obrig. |
|---|---|---|---|---|
| 1 | email | Coletado pelo bot / metadata | <? $email_lead ?> | Sim |
| 2 | firstname | Coletado / metadata.contactName | <? $primeiro_nome ?> | Não |
| 3 | lastname | Coletado / metadata.contactName | <? $sobrenome ?> | Não |
| 4 | phone | message.from / metadata | <? $telefone ?> | Não |
| # | HubSpot Property | Fonte | Variável Bot | Obrig. |
|---|---|---|---|---|
| 5 | pet_name | Coletado pelo bot | <? $nome_pet ?> | Não |
| 6 | pet_species | Coletado pelo bot | <? $especie_pet ?> | Não |
| # | HubSpot Property | Fonte | Tipo |
|---|---|---|---|
| 7 | zenvia_conversation_id | metadata.conversationId / conversation.id | text |
| 8 | zenvia_channel | channel (fixo: "whatsapp") | text |
| 9 | first_message | message.contents[0].text | text |
| 10 | zenvia_event_id | id | text |
| 11 | zenvia_subscription_id | subscriptionId | text |
| 12 | zenvia_event_type | type (MESSAGE, MESSAGE_STATUS) | text |
| 13 | zenvia_message_id | message.id | text |
| 14 | zenvia_direction | direction (IN/OUT) | text |
| 15 | zenvia_from | message.from | text |
| 16 | zenvia_to | message.to | text |
| 17 | zenvia_content_type | message.contents[0].type | text |
| 18 | zenvia_timestamp | timestamp | text |
| 19 | zenvia_message_status | messageStatus.code | text |
| 20 | zenvia_whatsapp_name | message.visitor.name | text |
| 21 | zenvia_bot_flow_id | metadata (custom) | text |
| 22 | zenvia_metadata | metadata (JSON string) | text |
| # | HubSpot Property | Fonte | Uso |
|---|---|---|---|
| 23 | zenvia_referral_headline | message.referral.headline | Headline do anúncio CTWA |
| 24 | zenvia_referral_source_type | message.referral.source.type | Tipo: ad, post |
| 25 | zenvia_referral_source_url | message.referral.source.url | URL do anúncio |
| 26 | zenvia_referral_ctwa_id | message.referral.ctwaId | ID do Click-to-WhatsApp Ad |
| 27 | zenvia_contact_id | conversation.contactId | ID do contato na Zenvia |
| 28 | zenvia_flow_response_data | flow_response.data | Dados do WhatsApp Flow (JSON) |
| # | HubSpot Property | Fonte | Uso |
|---|---|---|---|
| 29 | zenvia_visitor_picture | message.visitor.picture | URL foto perfil WhatsApp |
| 30 | zenvia_status_description | messageStatus.description | Descrição do status |
| 31 | zenvia_status_error_code | messageStatus.causes[].channelErrorCode | Código de erro do canal |
| 32 | zenvia_status_error_reason | messageStatus.causes[].reason | Razão do erro |
| 33 | zenvia_channel_provider | message.channel.provider | Provider do canal |
| 34 | zenvia_message_payload | message.contents[].payload | Payload de botão clicado |
Copiar e colar no Postman (Import → Raw Text) ou executar no terminal para validar.
curl -X POST \
"https://api.hsforms.com/submissions/v3/integration/submit/50501903/a5edb59a-d033-4905-84d4-c00cbed2403e" \
-H "Content-Type: application/json" \
-d '{
"fields": [
{ "name": "email", "value": "teste.zenvia@petlove.com" },
{ "name": "firstname", "value": "Teste" },
{ "name": "phone", "value": "+5511999887766" },
{ "name": "zenvia_channel", "value": "whatsapp" },
{ "name": "first_message", "value": "Teste de integracao" }
],
"context": {
"pageUri": "https://api.zenvia.io/whatsapp",
"pageName": "Zenvia WhatsApp - PetLove"
}
}'
// HTTP 200 OK
{
"inlineMessage": "Thanks for submitting the form."
}
// HTTP 400 Bad Request
{
"status": "error",
"message": "The request is not valid",
"errors": [
{ "message": "Required field 'email' is missing" }
]
}
| HTTP | Causa | Ação |
|---|---|---|
| 200 | Sucesso. Contato criado/atualizado. | Nenhuma. |
| 400 | Campo obrigatório ausente ou validação falhou. | Verificar errors[].message. Não reenviar. |
| 404 | Form ID ou Portal ID incorreto. | Verificar IDs na URL. |
| 429 | Rate limit (100 req/10s). | Backoff exponencial. Esperar 10s. |
| 5xx | Erro interno HubSpot. | Retry com backoff. Se persistir, contatar HubSpot. |
Após a submissão via Forms API, o HubSpot dispara automaticamente workflows com trigger "Contact submits a form" filtrado pelo formulário Zenvia.
| # | Ação | Detalhes |
|---|---|---|
| 1 | Criar Deal | Pipeline de vendas PetLove, estágio inicial |
| 2 | Atribuir vendedor | Baseado em round-robin ou regra de território |
| 3 | Enviar notificação | Email/Slack para vendedor atribuído |
| 4 | Setar lifecycle stage | Lead ou MQL conforme critérios |
| # | Tarefa | Quem | Status |
|---|---|---|---|
| 0 | BLOCKER: Gerar novo token Zenvia API v2 (atual retorna 401). Deadline: 10/03/2026 | PetLove / Zenvia | Bloqueado |
| 1 | 34 properties customizadas criadas no grupo "Integração Zenvia" | EPIC | Feito |
| 2 | Formulário criado com 34 campos (4 categorias) | EPIC | Feito |
| 3 | PoC validada em produção (6 contatos, 7 cenários E2E) | EPIC | Feito |
| 4 | Documento de integração (este documento) | EPIC | Feito |
| 5 | Configurar "Chamada de API" no builder do bot (Seção 3) | Zenvia / PetLove | Pendente |
| 6 | Mapear variáveis do bot para campos HubSpot (Seção 6) | Zenvia / PetLove | Pendente |
| 7 | Garantir coleta de email no fluxo do bot (obrigatório) | Zenvia / PetLove | Pendente |
| 8 | Testar via Postman/cURL (Seção 7) | Zenvia / PetLove | Pendente |
| 9 | Implementar retry para erros 429/5xx | Zenvia / PetLove | Pendente |
| 10 | Workflow de atribuição de vendedor | EPIC | Pendente |
| 11 | Desenvolvimento e testes (validação técnica do fluxo completo com dados reais) | EPIC | Pendente |
| 12 | Homologação e validação dos eventos (confirmar que todos os eventos Zenvia chegam corretamente no HubSpot e disparam workflows) | EPIC | Pendente |
A Forms API cria contatos e dispara workflows, mas não permite:
| Limitação da V1 (Forms API) | Como o middleware resolve |
|---|---|
| Não busca dados complementares do contato na Zenvia | GET /contacts/{id} na Zenvia API para enriquecer o contato |
| Não aplica regras de ownership (vendedor dono) | Mapeia userId Zenvia → email → ownerId HubSpot |
| Não aplica regras de negócio (janela 24h, carteira 15 dias, 1 negócio por vez) | Lógica customizada antes de gravar no HubSpot |
| Não cria Deal, Communication e Atendimento automaticamente | Cria todos os objetos e associações via HubSpot API |
| Sem fila de retry e idempotência | Bull/Redis com Dead Letter Queue, processamento idempotente |
| Sem log centralizado e auditoria | Código versionado em Git, logging, healthcheck, alertas |
| Dados sensíveis trafegam direto para o HubSpot — sem camada de tratamento | Middleware intercepta, sanitiza e transforma os dados ANTES de gravar no HubSpot — dados sensíveis podem ser mascarados, filtrados ou redirecionados sem nunca tocar o CRM |
| Passo | Ação | Detalhe |
|---|---|---|
| 1 | Recebe POST da Zenvia (webhook) | Endpoint HTTP próprio com autenticação |
| 2 | Valida e coloca na fila | Autenticação + Bull/Redis para idempotência |
| 3 | Busca dados completos na Zenvia | GET /contacts/{id} — nome, email, telefone, histórico |
| 4 | Aplica regras de negócio | Ownership (userId → email → ownerId), janela 24h, carteira 15 dias, 1 negócio/vez |
| 5 | Grava no HubSpot via API | Cria/atualiza Contact, Deal, Communication, Atendimento, Owner |
| Capacidade | Detalhe |
|---|---|
| Stack | Node.js/Express, controlado pela EPIC |
| Chamadas externas | Ilimitadas (Zenvia GET, HubSpot API, etc.) |
| Timeout | Sem limite (diferente dos 20s do Custom Code HubSpot) |
| Fila de processamento | Bull/Redis com retry, Dead Letter Queue, idempotência |
| Versionamento | Git — testável, debugável, auditável |
| Hospedagem | Railway, Render, AWS, GCP ou qualquer cloud |
| Ops Hub | NÃO precisa de Operations Hub nem de nenhum add-on |
| Prós | Contras |
|---|---|
|
|
| Item | V1 (Forms API) | V2 (Middleware) |
|---|---|---|
| Criação de contato | Automático | Automático |
| Dados do bot (34 campos) | Sim | Sim + enriquecidos |
| Busca dados complementares Zenvia | Não | GET /contacts/{id} |
| Regras de ownership | Não | userId → ownerId |
| Regras de negócio (janela 24h) | Não | Lógica customizada |
| Cria Deal automaticamente | Via workflow | Via API (middleware) |
| Communication / Atendimento | Não | Cria e associa |
| Fila com retry / DLQ | Não | Bull/Redis |
| Auditoria / Git | Não | Versionado |
| Tratamento de dados sensíveis | Sem tratamento — dados vão direto ao CRM | Mascaramento, filtragem, redirecionamento (LGPD) |
Referência: Análise Técnica — Integração Zenvia × HubSpot v1.0 (baseado no Brief Técnico v3.2), Jonathan Lima, 05/03/2026.
| Papel | Nome | Contato |
|---|---|---|
| Arquitetura da Integração | Fabio Munhoz (Arquiteto de Receita) | munhoz@epic.digital |
| Suporte Técnico | Jonathan Lima | jonathan.lima@epic.digital |