Central de Docs

EDUZZ-HS-TI-003

API de
Formularios HubSpot

Documentacao tecnica para integracao de formularios com o HubSpot Service Hub. Guia completo para o time de tecnologia.

Secao 01

Visao Geral

A API de Formularios do HubSpot permite criar tickets automaticamente a partir de submissoes de formularios externos. Ideal para integracao com chat, portais e sistemas internos.

Base URL
api.hsforms.com
Portal ID
4011243
EPIC Digital - Partner Admin
Autenticacao
Nao requer token para Forms API (submissao publica)
â„šī¸
Forms API vs CRM API
A Forms API e publica e nao requer autenticacao. Para operacoes que exigem autenticacao (criar tickets via CRM API), consulte o documento EDUZZ-HS-TI-002.

Secao 02

Autenticacao e Credenciais

🔐 Private App - Epic Forms

Propriedade Valor
Nome Epic Forms
Token pat-na1-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Account ID 4011243

Escopos Configurados

Escopo Descricao
forms Acesso a Forms API
forms-uploaded-files Download de arquivos enviados via formularios
external_integrations.forms.access Criar, editar e clonar formularios HubSpot
tickets Criar, editar e excluir tickets
crm.objects.contacts.read Leitura de contatos
crm.objects.deals.read Leitura de deals
crm.schemas.contacts.read Leitura de propriedades de contatos
crm.schemas.deals.read Leitura de propriedades de deals
analytics.behavioral_events.send Envio de eventos comportamentais
âš ī¸
Seguranca
O token deve ser armazenado em variaveis de ambiente. NUNCA exponha em codigo frontend. Use sempre HTTPS para todas as requisicoes.

Secao 03

Forms API - Submissao de Formularios

POST /submissions/v3/integration/submit/{portalId}/{formGuid}

Submete dados de formulario para o HubSpot. Pode criar contatos, tickets e disparar workflows.

URL Base

https://api.hsforms.com/submissions/v3/integration/submit/4011243/{formGuid}

Headers

Header Valor Obrigatorio
Content-Type application/json Sim

Request Body

{ "submittedAt": "1677654321000", "fields": [ { "objectTypeId": "0-1", "name": "email", "value": "cliente@exemplo.com" }, { "objectTypeId": "0-1", "name": "firstname", "value": "Joao" }, { "objectTypeId": "0-1", "name": "lastname", "value": "Silva" }, { "objectTypeId": "0-5", "name": "subject", "value": "Problema com acesso a plataforma" }, { "objectTypeId": "0-5", "name": "content", "value": "Descricao detalhada do problema..." }, { "objectTypeId": "0-5", "name": "hs_pipeline", "value": "824388612" }, { "objectTypeId": "0-5", "name": "hs_pipeline_stage", "value": "1" } ], "context": { "hutk": "tracking_cookie_value", "pageUri": "https://eduzz.com/suporte", "pageName": "Formulario de Suporte" } }

📝 Object Type IDs

Object Type ID Objeto Descricao
0-1 Contact Campos do contato (email, nome, telefone)
0-2 Company Campos da empresa
0-5 Ticket Campos do ticket (subject, content, pipeline)

Secao 04

Propriedades de Ticket

Todas as propriedades disponiveis para criacao de tickets via formulario. Use o objectTypeId: "0-5" para campos de ticket.

📋 Campos Nativos HubSpot

Nome Interno Tipo Descricao Obrigatorio
subject string Titulo/Assunto do ticket Sim
content string Descricao/Corpo do ticket Sim
hs_pipeline string ID do pipeline Sim
hs_pipeline_stage string ID do stage (status inicial) Sim
hs_ticket_priority enumeration Prioridade: LOW, MEDIUM, HIGH Nao
source_type enumeration Origem: CHAT, EMAIL, FORM, PHONE Nao

🔧 Campos Customizados Eduzz

Nome Interno Tipo Opcoes/Valores Descricao
tipo_ticket enumeration incidente, requisicao Tipo do ticket
incidente enumeration acesso, conta, financeiro, tecnico, reclame_aqui Categoria do incidente
tipo_incidente_acesso enumeration [ver catalogo] Subcategoria de acesso
tipo_incidente_conta enumeration [ver catalogo] Subcategoria de conta
tipo_incidente_financeiro enumeration [ver catalogo] Subcategoria financeiro
tipo_incidente_tecnico enumeration [ver catalogo] Subcategoria tecnico
tipo_incidente_reclame_aqui enumeration [ver catalogo] Subcategoria Reclame Aqui
link_reclame_aqui string URL Link da reclamacao no RA
grupo_tecnico enumeration [grupos disponiveis] Equipe responsavel
fluxo_origem enumeration chat, email, formulario, interno Canal de origem
nome_conta string - Nome da conta Eduzz
tipo_cliente enumeration white, black, gold, diamond Belt do cliente
id_chat_hyperflow string - ID da conversa no HyperFlow
temperatura_ticket enumeration fria, morna, quente Temperatura do ticket
acao_de_vendas boolean true, false Relacionado a lancamento
nivel_atendimento enumeration n1, n2, n3 Nivel de atendimento
motivo_escalonamento string - Justificativa de escalonamento

đŸ”ĸ IDs de Pipelines

Pipeline ID Stage "Novo"
Suporte | Principal 824265261 1
Suporte N1 | Humano 824388612 1
Suporte N1 | Chat 855455576 1
Suporte N2 824265268 1
Suporte | N3 T.I 824388613 1

Secao 05

Exemplos de Integracao

📱 Exemplo 1: Ticket via Chat HyperFlow

// JavaScript - Integracao HyperFlow const criarTicketHyperFlow = async (dadosChat) => { const payload = { submittedAt: Date.now().toString(), fields: [ // Dados do contato { objectTypeId: "0-1", name: "email", value: dadosChat.clienteEmail }, { objectTypeId: "0-1", name: "firstname", value: dadosChat.clienteNome }, // Dados do ticket { objectTypeId: "0-5", name: "subject", value: dadosChat.assunto }, { objectTypeId: "0-5", name: "content", value: dadosChat.historico }, { objectTypeId: "0-5", name: "hs_pipeline", value: "824388612" }, { objectTypeId: "0-5", name: "hs_pipeline_stage", value: "1" }, // Campos customizados { objectTypeId: "0-5", name: "fluxo_origem", value: "chat" }, { objectTypeId: "0-5", name: "id_chat_hyperflow", value: dadosChat.chatId }, { objectTypeId: "0-5", name: "tipo_ticket", value: dadosChat.tipo }, { objectTypeId: "0-5", name: "nome_conta", value: dadosChat.contaEduzz } ], context: { pageUri: "https://hyperflow.eduzz.com", pageName: "HyperFlow Chat" } }; const response = await fetch( "https://api.hsforms.com/submissions/v3/integration/submit/4011243/FORM_GUID", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) } ); return response.json(); };

âš ī¸ Exemplo 2: Ticket Reclame Aqui (Prioridade Urgente)

// JavaScript - Ticket Reclame Aqui const criarTicketReclameAqui = async (reclamacao) => { const payload = { submittedAt: Date.now().toString(), fields: [ // Dados do contato { objectTypeId: "0-1", name: "email", value: reclamacao.email }, { objectTypeId: "0-1", name: "firstname", value: reclamacao.nome }, // Dados do ticket { objectTypeId: "0-5", name: "subject", value: `[RECLAME AQUI] ${reclamacao.titulo}` }, { objectTypeId: "0-5", name: "content", value: reclamacao.descricao }, { objectTypeId: "0-5", name: "hs_pipeline", value: "824388612" }, { objectTypeId: "0-5", name: "hs_pipeline_stage", value: "1" }, { objectTypeId: "0-5", name: "hs_ticket_priority", value: "HIGH" }, // Campos customizados - Reclame Aqui { objectTypeId: "0-5", name: "tipo_ticket", value: "incidente" }, { objectTypeId: "0-5", name: "incidente", value: "reclame_aqui" }, { objectTypeId: "0-5", name: "link_reclame_aqui", value: reclamacao.url }, { objectTypeId: "0-5", name: "fluxo_origem", value: "formulario" }, { objectTypeId: "0-5", name: "temperatura_ticket", value: "quente" } ] }; return await submitForm(payload); };

📝 Exemplo 3: Formulario Completo de Teste

// Payload completo com todas as propriedades para teste const payloadCompleto = { submittedAt: Date.now().toString(), fields: [ // ========== CONTATO ========== { objectTypeId: "0-1", name: "email", value: "teste@eduzz.com" }, { objectTypeId: "0-1", name: "firstname", value: "Usuario" }, { objectTypeId: "0-1", name: "lastname", value: "Teste" }, { objectTypeId: "0-1", name: "phone", value: "11999999999" }, // ========== TICKET - CAMPOS NATIVOS ========== { objectTypeId: "0-5", name: "subject", value: "Ticket de Teste Completo" }, { objectTypeId: "0-5", name: "content", value: "Descricao completa do ticket de teste" }, { objectTypeId: "0-5", name: "hs_pipeline", value: "824388612" }, { objectTypeId: "0-5", name: "hs_pipeline_stage", value: "1" }, { objectTypeId: "0-5", name: "hs_ticket_priority", value: "MEDIUM" }, { objectTypeId: "0-5", name: "source_type", value: "FORM" }, // ========== TICKET - CAMPOS CUSTOMIZADOS ========== // Classificacao { objectTypeId: "0-5", name: "tipo_ticket", value: "incidente" }, { objectTypeId: "0-5", name: "incidente", value: "tecnico" }, { objectTypeId: "0-5", name: "tipo_incidente_tecnico", value: "erro_sistema" }, // Origem e Roteamento { objectTypeId: "0-5", name: "fluxo_origem", value: "formulario" }, { objectTypeId: "0-5", name: "grupo_tecnico", value: "suporte_n1" }, { objectTypeId: "0-5", name: "nivel_atendimento", value: "n1" }, // Cliente { objectTypeId: "0-5", name: "nome_conta", value: "Conta Teste 123" }, { objectTypeId: "0-5", name: "tipo_cliente", value: "gold" }, // Priorizacao { objectTypeId: "0-5", name: "temperatura_ticket", value: "morna" }, { objectTypeId: "0-5", name: "acao_de_vendas", value: "false" }, // Integracao Chat (se aplicavel) { objectTypeId: "0-5", name: "id_chat_hyperflow", value: "CHAT-123456" }, // Reclame Aqui (se aplicavel) { objectTypeId: "0-5", name: "link_reclame_aqui", value: "" } ], context: { pageUri: "https://eduzz.com/suporte/teste", pageName: "Formulario de Teste Completo" } };

🐍 Exemplo 4: Python

import requests import time def criar_ticket(dados_ticket): """ Cria um ticket no HubSpot via Forms API """ url = "https://api.hsforms.com/submissions/v3/integration/submit/4011243/FORM_GUID" payload = { "submittedAt": str(int(time.time() * 1000)), "fields": [ {"objectTypeId": "0-1", "name": "email", "value": dados_ticket["email"]}, {"objectTypeId": "0-1", "name": "firstname", "value": dados_ticket["nome"]}, {"objectTypeId": "0-5", "name": "subject", "value": dados_ticket["assunto"]}, {"objectTypeId": "0-5", "name": "content", "value": dados_ticket["descricao"]}, {"objectTypeId": "0-5", "name": "hs_pipeline", "value": "824388612"}, {"objectTypeId": "0-5", "name": "hs_pipeline_stage", "value": "1"}, {"objectTypeId": "0-5", "name": "tipo_ticket", "value": dados_ticket.get("tipo", "requisicao")}, {"objectTypeId": "0-5", "name": "fluxo_origem", "value": dados_ticket.get("origem", "formulario")} ] } headers = {"Content-Type": "application/json"} response = requests.post(url, json=payload, headers=headers) return response.json() # Exemplo de uso ticket = criar_ticket({ "email": "cliente@exemplo.com", "nome": "Joao Silva", "assunto": "Problema com login", "descricao": "Nao consigo acessar minha conta", "tipo": "incidente", "origem": "formulario" })

Secao 06

CRM API - Criacao Direta de Tickets

Para cenarios que exigem mais controle, use a CRM API com autenticacao.

POST /crm/v3/objects/tickets

Cria um ticket diretamente via CRM API. Requer autenticacao com Private App token.

Headers

Header Valor
Authorization Bearer pat-na1-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Content-Type application/json

Request Body

{ "properties": { "subject": "Titulo do Ticket", "content": "Descricao detalhada", "hs_pipeline": "824388612", "hs_pipeline_stage": "1", "hs_ticket_priority": "MEDIUM", "tipo_ticket": "incidente", "incidente": "tecnico", "fluxo_origem": "chat", "nome_conta": "Conta do Cliente", "id_chat_hyperflow": "CHAT-123" }, "associations": [ { "to": { "id": "12345" }, "types": [ { "associationCategory": "HUBSPOT_DEFINED", "associationTypeId": 16 } ] } ] }

🔗 Association Type IDs

Associacao Type ID Descricao
Ticket → Contact 16 Vincula ticket a um contato
Ticket → Company 26 Vincula ticket a uma empresa
Ticket → Ticket Custom Labels: N1, N2, N3, Principal

Secao 07

Webhooks e Eventos

Configure webhooks para receber notificacoes em tempo real sobre eventos de tickets.

📡 Eventos Disponiveis

Evento Subscription Type Descricao
Ticket Criado ticket.creation Disparado quando um ticket e criado
Ticket Atualizado ticket.propertyChange Disparado quando propriedade muda
Ticket Deletado ticket.deletion Disparado quando ticket e deletado

đŸ“Ŧ Payload do Webhook

[ { "objectId": 12345, "propertyName": "hs_pipeline_stage", "propertyValue": "2", "changeSource": "CRM", "eventId": 1234567890, "subscriptionId": 123456, "portalId": 4011243, "appId": 2905413, "occurredAt": 1677654321000, "subscriptionType": "ticket.propertyChange", "attemptNumber": 0 } ]

Secao 08

Boas Praticas

Rate Limits
Forms API: 10 req/seg
CRM API: 100 req/10seg (Private App)
Retry Logic
Implemente retry com backoff exponencial para erros 429 (rate limit) e 5xx
Validacao
Valide todos os campos antes de enviar. E-mail deve ser valido para criar contato.
Idempotencia
Use identificadores unicos para evitar tickets duplicados em caso de retry.
âš ī¸
Importante: Ambiente de Producao
O ambiente HubSpot da Eduzz e de PRODUCAO. Todas as alteracoes requerem aprovacao do responsavel tecnico. Nao crie propriedades, workflows ou pipelines sem autorizacao.

Secao 09

Suporte e Contato

Responsavel Tecnico
Marcus Picoli (Eduzz)
Implementacao
Fabio Munhoz (EPIC Digital)
Integracao HyperFlow
Lucas Toyoda (Eduzz)