Como Usar a API do HubSpot em 2026

Ashley Innocent

Ashley Innocent

25 março 2026

Como Usar a API do HubSpot em 2026

Resumo

A API do HubSpot permite que desenvolvedores se integrem programaticamente com hubs de CRM, marketing, vendas e serviços. Ela usa autenticação OAuth 2.0 e de aplicativos privados, endpoints RESTful para contatos, empresas, negócios (deals), tickets e muito mais, com limites de taxa baseados no nível de assinatura. Este guia aborda a configuração de autenticação, endpoints principais, webhooks e estratégias de integração em produção.

Introdução

O HubSpot gerencia mais de 194.000 contas de clientes e bilhões de registros de CRM. Para desenvolvedores que constroem integrações de CRM, automação de marketing ou ferramentas de vendas, a integração com a API do HubSpot não é opcional — é essencial para alcançar mais de 7 milhões de usuários.

Aqui está a realidade: empresas perdem de 15 a 20 horas semanais com entrada manual de dados entre sistemas. Uma integração sólida com a API do HubSpot automatiza a sincronização de contatos, atualizações de negócios, fluxos de trabalho de marketing e relatórios entre plataformas.

💡
Apidog simplifica o teste de integração de API. Teste seus endpoints do HubSpot, valide fluxos OAuth, inspecione payloads de webhooks e depure problemas de autenticação em um único espaço de trabalho. Importe especificações de API, simule respostas e compartilhe cenários de teste com sua equipe.
botão

O Que É a API do HubSpot?

O HubSpot fornece uma API RESTful para acessar dados de CRM e recursos de automação de marketing. A API lida com:

Principais Recursos

Recurso Descrição
Design RESTful Métodos HTTP padrão com respostas JSON
OAuth 2.0 + Aplicativos Privados Opções de autenticação flexíveis
Webhooks Notificações em tempo real para alterações de objetos
Limitação de Taxas Limites baseados em níveis (100-400 requisições/segundo)
Objetos CRM Suporte para objetos padrão e personalizados
Associações Conecta objetos (contato-empresa, negócio-contato)
Propriedades Campos personalizados para qualquer tipo de objeto
API de Pesquisa Filtragem e ordenação complexas

Visão Geral da Arquitetura da API

O HubSpot usa APIs REST versionadas:

https://api.hubapi.com/

Versões da API Comparadas

Versão Status Autenticação Caso de Uso
CRM API v3 Atual OAuth 2.0, Aplicativo Privado Todas as novas integrações
Automation API v4 Atual OAuth 2.0, Aplicativo Privado Inscrição em fluxos de trabalho
Marketing Email API Atual OAuth 2.0, Aplicativo Privado Campanhas de e-mail
Contacts API v1 Obsoleta Chave de API (legado) Migrar para v3
Companies API v1 Obsoleta Chave de API (legado) Migrar para v3

Importante: O HubSpot descontinuou a autenticação por chave de API em favor do OAuth 2.0 e aplicativos privados. Migre todas as integrações imediatamente.

Primeiros Passos: Configuração da Autenticação

Passo 1: Crie Sua Conta de Desenvolvedor HubSpot

Antes de acessar a API:

  1. Visite o Portal do Desenvolvedor HubSpot
  2. Faça login com sua conta HubSpot (ou crie uma)
  3. Navegue até Aplicativos no painel do desenvolvedor
  4. Clique em Criar aplicativo

Passo 2: Escolha o Método de Autenticação

O HubSpot suporta dois métodos de autenticação:

Método Melhor Para Nível de Segurança
OAuth 2.0 Aplicativos multi-tenant, integrações públicas Alto (tokens com escopo de usuário)
Aplicativo Privado Integrações internas, portal único Alto (token com escopo de portal)

Passo 3: Configurar Aplicativo Privado (Recomendado para Integrações Internas)

Crie um aplicativo privado para acesso de portal único:

  1. Vá para Configurações > Integrações > Aplicativos Privados
  2. Clique em Criar um aplicativo privado
  3. Configure os escopos:
contacts
crm.objects.companies
crm.objects.deals
crm.objects.tickets
automation
webhooks
  1. Gere o token de acesso
  2. Copie e armazene com segurança
# .env file
HUBSPOT_ACCESS_TOKEN="pat-na1-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
HUBSPOT_PORTAL_ID="12345678"

Passo 4: Configurar OAuth 2.0 (Para Aplicativos Multi-Tenant)

Configure OAuth para acesso multi-portal:

const HUBSPOT_CLIENT_ID = process.env.HUBSPOT_CLIENT_ID;
const HUBSPOT_CLIENT_SECRET = process.env.HUBSPOT_CLIENT_SECRET;
const HUBSPOT_REDIRECT_URI = process.env.HUBSPOT_REDIRECT_URI;

// Build authorization URL
const getAuthUrl = (state) => {
  const params = new URLSearchParams({
    client_id: HUBSPOT_CLIENT_ID,
    redirect_uri: HUBSPOT_REDIRECT_URI,
    scope: 'crm.objects.contacts.read crm.objects.contacts.write',
    state: state,
    optional_scope: 'crm.objects.deals.read'
  });

  return `https://app.hubspot.com/oauth/authorize?${params.toString()}`;
};

Passo 5: Trocar Código por Token de Acesso

Lidar com o callback OAuth:

const exchangeCodeForToken = async (code) => {
  const response = await fetch('https://api.hubapi.com/oauth/v1/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: new URLSearchParams({
      grant_type: 'authorization_code',
      client_id: HUBSPOT_CLIENT_ID,
      client_secret: HUBSPOT_CLIENT_SECRET,
      redirect_uri: HUBSPOT_REDIRECT_URI,
      code: code
    })
  });

  const data = await response.json();

  return {
    accessToken: data.access_token,
    refreshToken: data.refresh_token,
    expiresIn: data.expires_in,
    portalId: data.hub_portal_id
  };
};

// Handle callback
app.get('/oauth/callback', async (req, res) => {
  const { code, state } = req.query;

  try {
    const tokens = await exchangeCodeForToken(code);

    // Store tokens in database
    await db.installations.create({
      portalId: tokens.portalId,
      accessToken: tokens.accessToken,
      refreshToken: tokens.refreshToken,
      tokenExpiry: Date.now() + (tokens.expiresIn * 1000)
    });

    res.redirect('/success');
  } catch (error) {
    console.error('OAuth error:', error);
    res.status(500).send('Authentication failed');
  }
});

Passo 6: Atualizar Token de Acesso

Tokens de acesso expiram após 6 horas:

const refreshAccessToken = async (refreshToken) => {
  const response = await fetch('https://api.hubapi.com/oauth/v1/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: new URLSearchParams({
      grant_type: 'refresh_token',
      client_id: HUBSPOT_CLIENT_ID,
      client_secret: HUBSPOT_CLIENT_SECRET,
      redirect_uri: HUBSPOT_REDIRECT_URI,
      refresh_token: refreshToken
    })
  });

  const data = await response.json();

  return {
    accessToken: data.access_token,
    refreshToken: data.refresh_token, // Always save new refresh token
    expiresIn: data.expires_in
  };
};

// Middleware to ensure valid token
const ensureValidToken = async (portalId) => {
  const installation = await db.installations.findByPortalId(portalId);

  // Refresh if expires within 30 minutes
  if (installation.tokenExpiry < Date.now() + 1800000) {
    const newTokens = await refreshAccessToken(installation.refreshToken);

    await db.installations.update(installation.id, {
      accessToken: newTokens.accessToken,
      refreshToken: newTokens.refreshToken,
      tokenExpiry: Date.now() + (newTokens.expiresIn * 1000)
    });

    return newTokens.accessToken;
  }

  return installation.accessToken;
};

Passo 7: Fazer Chamadas de API Autenticadas

Crie um cliente de API reutilizável:

const HUBSPOT_BASE_URL = 'https://api.hubapi.com';

const hubspotRequest = async (endpoint, options = {}, portalId = null) => {
  const accessToken = portalId ? await ensureValidToken(portalId) : process.env.HUBSPOT_ACCESS_TOKEN;

  const response = await fetch(`${HUBSPOT_BASE_URL}${endpoint}`, {
    ...options,
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
      ...options.headers
    }
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`HubSpot API Error: ${error.message}`);
  }

  return response.json();
};

// Usage
const contacts = await hubspotRequest('/crm/v3/objects/contacts');

Trabalhando com Objetos CRM

Criando um Contato

Crie ou atualize um contato:

const createContact = async (contactData) => {
  const contact = {
    properties: {
      email: contactData.email,
      firstname: contactData.firstName,
      lastname: contactData.lastName,
      phone: contactData.phone,
      company: contactData.company,
      website: contactData.website,
      lifecyclestage: contactData.lifecycleStage || 'lead'
    }
  };

  const response = await hubspotRequest('/crm/v3/objects/contacts', {
    method: 'POST',
    body: JSON.stringify(contact)
  });

  return response;
};

// Usage
const contact = await createContact({
  email: 'john.doe@example.com',
  firstName: 'John',
  lastName: 'Doe',
  phone: '+1-555-0123',
  company: 'Acme Corp',
  lifecycleStage: 'customer'
});

console.log(`Contact created: ${contact.id}`);

Propriedades do Contato

Propriedade Tipo Descrição
email String E-mail principal (identificador único)
firstname String Primeiro nome
lastname String Sobrenome
phone String Número de telefone
company String Nome da empresa
website String URL do site
lifecyclestage Enum lead, marketingqualifiedlead, salesqualifiedlead, opportunity, customer, evangelist, subscriber
createdate DateTime Gerado automaticamente
lastmodifieddate DateTime Gerado automaticamente

Obtendo um Contato

Busque um contato por ID:

const getContact = async (contactId) => {
  const response = await hubspotRequest(`/crm/v3/objects/contacts/${contactId}`);
  return response;
};

// Usage
const contact = await getContact('12345');
console.log(`${contact.properties.firstname} ${contact.properties.lastname}`);
console.log(`Email: ${contact.properties.email}`);

Pesquisando Contatos

Pesquise com filtros:

const searchContacts = async (searchCriteria) => {
  const response = await hubspotRequest('/crm/v3/objects/contacts/search', {
    method: 'POST',
    body: JSON.stringify({
      filterGroups: searchCriteria,
      properties: ['firstname', 'lastname', 'email', 'company'],
      limit: 100
    })
  });

  return response;
};

// Usage - Find contacts at specific company
const results = await searchContacts({
  filterGroups: [
    {
      filters: [
        {
          propertyName: 'company',
          operator: 'EQ',
          value: 'Acme Corp'
        }
      ]
    }
  ]
});

results.results.forEach(contact => {
  console.log(`${contact.properties.email}`);
});

Operadores de Filtro de Pesquisa

Operador Descrição Exemplo
EQ Igual a company EQ 'Acme'
NEQ Diferente de lifecyclestage NEQ 'subscriber'
CONTAINS_TOKEN Contém email CONTAINS_TOKEN 'gmail'
NOT_CONTAINS_TOKEN Não contém email NOT_CONTAINS_TOKEN 'test'
GT Maior que createdate GT '2026-01-01'
LT Menor que createdate LT '2026-12-31'
GTE Maior ou igual a deal_amount GTE 10000
LTE Menor ou igual a deal_amount LTE 50000
HAS_PROPERTY Possui valor phone HAS_PROPERTY
NOT_HAS_PROPERTY Valor ausente phone NOT_HAS_PROPERTY

Criando uma Empresa

Crie um registro de empresa:

const createCompany = async (companyData) => {
  const company = {
    properties: {
      name: companyData.name,
      domain: companyData.domain,
      industry: companyData.industry,
      numberofemployees: companyData.employees,
      annualrevenue: companyData.revenue,
      city: companyData.city,
      state: companyData.state,
      country: companyData.country
    }
  };

  const response = await hubspotRequest('/crm/v3/objects/companies', {
    method: 'POST',
    body: JSON.stringify(company)
  });

  return response;
};

// Usage
const company = await createCompany({
  name: 'Acme Corporation',
  domain: 'acme.com',
  industry: 'Technology',
  employees: 500,
  revenue: 50000000,
  city: 'San Francisco',
  state: 'CA',
  country: 'USA'
});

Associando Objetos

Vincule contatos a empresas:

const associateContactWithCompany = async (contactId, companyId) => {
  const response = await hubspotRequest(
    `/crm/v3/objects/contacts/${contactId}/associations/companies/${companyId}`,
    {
      method: 'PUT',
      body: JSON.stringify({
        types: [
          {
            associationCategory: 'HUBSPOT_DEFINED',
            associationTypeId: 1 // Contact to Company
          }
        ]
      })
    }
  );

  return response;
};

// Usage
await associateContactWithCompany('12345', '67890');

Tipos de Associação

Associação ID do Tipo Direção
Contato → Empresa 1 Contato está associado à Empresa
Empresa → Contato 1 Empresa tem Contato associado
Negócio → Contato 3 Negócio está associado ao Contato
Negócio → Empresa 5 Negócio está associado à Empresa
Ticket → Contato 16 Ticket está associado ao Contato
Ticket → Empresa 15 Ticket está associado à Empresa

Criando um Negócio

Crie uma oportunidade de vendas:

const createDeal = async (dealData) => {
  const deal = {
    properties: {
      dealname: dealData.name,
      amount: dealData.amount.toString(),
      dealstage: dealData.stage || 'appointmentscheduled',
      pipeline: dealData.pipelineId || 'default',
      closedate: dealData.closeDate,
      dealtype: dealData.type || 'newbusiness',
      description: dealData.description
    }
  };

  const response = await hubspotRequest('/crm/v3/objects/deals', {
    method: 'POST',
    body: JSON.stringify(deal)
  });

  return response;
};

// Usage
const deal = await createDeal({
  name: 'Acme Corp - Enterprise License',
  amount: 50000,
  stage: 'qualification',
  closeDate: '2026-06-30',
  type: 'newbusiness',
  description: 'Enterprise annual subscription'
});

// Associate with company and contact
await hubspotRequest(
  `/crm/v3/objects/deals/${deal.id}/associations/companies/${companyId}`,
  { method: 'PUT', body: JSON.stringify({ types: [{ associationCategory: 'HUBSPOT_DEFINED', associationTypeId: 5 }] }) }
);

await hubspotRequest(
  `/crm/v3/objects/deals/${deal.id}/associations/contacts/${contactId}`,
  { method: 'PUT', body: JSON.stringify({ types: [{ associationCategory: 'HUBSPOT_DEFINED', associationTypeId: 3 }] }) }
);

Estágios do Negócio (Pipeline Padrão)

Estágio Valor Interno
Compromissos Agendados appointmentscheduled
Qualificado para Comprar qualifiedtobuy
Apresentação Agendada presentationscheduled
Tomador de Decisão Comprometido decisionmakerboughtin
Contrato Enviado contractsent
Fechado e Ganho closedwon
Fechado e Perdido closedlost

Webhooks

Configurando Webhooks

Configure webhooks para notificações em tempo real:

const createWebhook = async (webhookData) => {
  const response = await hubspotRequest('/webhooks/v3/my-app/webhooks', {
    method: 'POST',
    body: JSON.stringify({
      webhookUrl: webhookData.url,
      eventTypes: webhookData.events,
      objectType: webhookData.objectType,
      propertyName: webhookData.propertyName // Optional: filter by property change
    })
  });

  return response;
};

// Usage
const webhook = await createWebhook({
  url: 'https://myapp.com/webhooks/hubspot',
  events: [
    'contact.creation',
    'contact.propertyChange',
    'company.creation',
    'deal.creation',
    'deal.stageChange'
  ],
  objectType: 'contact'
});

console.log(`Webhook created: ${webhook.id}`);

Tipos de Eventos de Webhook

Tipo de Evento Gatilho
contact.creation Novo contato criado
contact.propertyChange Propriedade de contato atualizada
contact.deletion Contato excluído
company.creation Nova empresa criada
company.propertyChange Propriedade da empresa atualizada
deal.creation Novo negócio criado
deal.stageChange Estágio do negócio alterado
deal.propertyChange Propriedade do negócio atualizada
ticket.creation Novo ticket criado
ticket.propertyChange Propriedade do ticket atualizada

Manipulando Webhooks

const express = require('express');
const crypto = require('crypto');
const app = express();

app.post('/webhooks/hubspot', express.json(), async (req, res) => {
  const signature = req.headers['x-hubspot-signature'];
  const payload = JSON.stringify(req.body);

  // Verify webhook signature
  const isValid = verifyWebhookSignature(payload, signature, process.env.HUBSPOT_CLIENT_SECRET);

  if (!isValid) {
    console.error('Invalid webhook signature');
    return res.status(401).send('Unauthorized');
  }

  const events = req.body;

  for (const event of events) {
    console.log(`Event: ${event.eventType}`);
    console.log(`Object: ${event.objectType} - ${event.objectId}`);
    console.log(`Property: ${event.propertyName}`);
    console.log(`Value: ${event.propertyValue}`);

    // Route to appropriate handler
    switch (event.eventType) {
      case 'contact.creation':
        await handleContactCreation(event);
        break;
      case 'contact.propertyChange':
        await handleContactUpdate(event);
        break;
      case 'deal.stageChange':
        await handleDealStageChange(event);
        break;
    }
  }

  res.status(200).send('OK');
});

function verifyWebhookSignature(payload, signature, clientSecret) {
  const expectedSignature = crypto
    .createHmac('sha256', clientSecret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expectedSignature, 'hex')
  );
}

Limitação de Taxas

Entendendo os Limites de Taxa

O HubSpot aplica limites de taxa com base no nível de assinatura:

Nível Requisições/Segundo Requisições/Dia
Grátis/Inicial 100 100.000
Profissional 200 500.000
Empresarial 400 1.000.000

Exceder os limites resulta em respostas HTTP 429 (Muitas Requisições).

Cabeçalhos de Limite de Taxa

Cabeçalho Descrição
X-HubSpot-RateLimit-Second-Limit Máx. requisições por segundo
X-HubSpot-RateLimit-Second-Remaining Requisições restantes neste segundo
X-HubSpot-RateLimit-Second-Reset Segundos até o reset do limite por segundo
X-HubSpot-RateLimit-Daily-Limit Máx. requisições por dia
X-HubSpot-RateLimit-Daily-Remaining Requisições restantes hoje
X-HubSpot-RateLimit-Daily-Reset Segundos até o reset do limite diário

Implementando o Tratamento de Limite de Taxas

const makeRateLimitedRequest = async (endpoint, options = {}, maxRetries = 3) => {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await hubspotRequest(endpoint, options);

      // Log rate limit info
      const remaining = response.headers.get('X-HubSpot-RateLimit-Second-Remaining');
      if (remaining < 10) {
        console.warn(`Low rate limit remaining: ${remaining}`);
      }

      return response;
    } catch (error) {
      if (error.message.includes('429') && attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000;
        console.log(`Rate limited. Retrying in ${delay}ms...`);
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
};

// Rate limiter class
class HubSpotRateLimiter {
  constructor(requestsPerSecond = 90) { // Stay under limit
    this.queue = [];
    this.interval = 1000 / requestsPerSecond;
    this.processing = false;
  }

  async add(requestFn) {
    return new Promise((resolve, reject) => {
      this.queue.push({ requestFn, resolve, reject });
      this.process();
    });
  }

  async process() {
    if (this.processing || this.queue.length === 0) return;
    this.processing = true;

    while (this.queue.length > 0) {
      const { requestFn, resolve, reject } = this.queue.shift();
      try {
        const result = await requestFn();
        resolve(result);
      } catch (error) {
        reject(error);
      }
      if (this.queue.length > 0) {
        await new Promise(r => setTimeout(r, this.interval));
      }
    }
    this.processing = false;
  }
}

Lista de Verificação de Implantação em Produção

Antes de entrar em produção:


Casos de Uso no Mundo Real

Sincronização de CRM

Uma empresa SaaS sincroniza dados de clientes:

Encaminhamento de Leads

Uma agência de marketing automatiza a distribuição de leads:

Conclusão

A API do HubSpot oferece recursos abrangentes de CRM e automação de marketing. Principais pontos:

botão

Seção de Perguntas Frequentes

Como faço para autenticar com a API do HubSpot?

Use OAuth 2.0 para aplicativos multi-tenant ou aplicativos privados para integrações de portal único. A autenticação por chave de API foi descontinuada.

Quais são os limites de taxa do HubSpot?

Os limites de taxa variam de 100 requisições/segundo (Grátis) a 400 requisições/segundo (Empresarial), com limites diários de 100K a 1M de requisições.

Como faço para criar um contato no HubSpot?

Faça um POST para /crm/v3/objects/contacts com propriedades incluindo e-mail, primeiro nome, sobrenome e quaisquer campos personalizados.

Posso criar propriedades personalizadas?

Sim, use a API de Propriedades para criar campos personalizados para qualquer tipo de objeto.

Como funcionam os webhooks no HubSpot?

Configure webhooks nas configurações do seu aplicativo. O HubSpot envia requisições POST para o seu endpoint quando eventos específicos ocorrem.

Pratique o design de API no Apidog

Descubra uma forma mais fácil de construir e usar APIs