Cara Menggunakan HubSpot API di Tahun 2026

Ashley Innocent

Ashley Innocent

25 March 2026

Cara Menggunakan HubSpot API di Tahun 2026

Apidog untuk Perusahaan

Penerapan On-Premises

SSO & RBAC

Sesuai SOC 2

Jelajahi Apidog Enterprise

Intisari

HubSpot API memungkinkan pengembang untuk berintegrasi dengan hub CRM, pemasaran, penjualan, dan layanan secara terprogram. Ini menggunakan otentikasi OAuth 2.0 dan aplikasi pribadi, endpoint RESTful untuk kontak, perusahaan, penawaran (deals), tiket, dan lainnya, dengan batasan laju (rate limits) berdasarkan tingkat langganan. Panduan ini mencakup pengaturan otentikasi, endpoint inti, webhook, dan strategi integrasi produksi.

Pendahuluan

HubSpot mengelola lebih dari 194.000 akun pelanggan dan miliaran catatan CRM. Bagi pengembang yang membangun integrasi CRM, otomatisasi pemasaran, atau alat penjualan, integrasi HubSpot API bukanlah pilihan—ini penting untuk menjangkau lebih dari 7 juta pengguna.

Inilah kenyataannya: bisnis kehilangan 15-20 jam setiap minggu karena entri data manual antar sistem. Integrasi HubSpot API yang solid mengotomatiskan sinkronisasi kontak, pembaruan penawaran, alur kerja pemasaran, dan pelaporan di berbagai platform.

💡
Apidog menyederhanakan pengujian integrasi API. Uji endpoint HubSpot Anda, validasi alur OAuth, periksa payload webhook, dan debug masalah otentikasi dalam satu ruang kerja. Impor spesifikasi API, respons tiruan, dan bagikan skenario pengujian dengan tim Anda.
tombol

Apa Itu HubSpot API?

HubSpot menyediakan API RESTful untuk mengakses data CRM dan fitur otomatisasi pemasaran. API ini menangani:

Fitur Utama

Fitur Deskripsi
Desain RESTful Metode HTTP standar dengan respons JSON
OAuth 2.0 + Aplikasi Pribadi Opsi otentikasi yang fleksibel
Webhook Notifikasi real-time untuk perubahan objek
Pembatasan Laju (Rate Limiting) Batas berbasis tingkatan (100-400 permintaan/detik)
Objek CRM Dukungan objek standar dan kustom
Asosiasi Menghubungkan objek (kontak-perusahaan, penawaran-kontak)
Properti Bidang kustom untuk semua jenis objek
API Pencarian Penyaringan dan pengurutan yang kompleks

Ikhtisar Arsitektur API

HubSpot menggunakan API REST yang memiliki versi:

https://api.hubapi.com/

Perbandingan Versi API

Versi Status Otentikasi Kasus Penggunaan
CRM API v3 Saat Ini OAuth 2.0, Aplikasi Pribadi Semua integrasi baru
Automation API v4 Saat Ini OAuth 2.0, Aplikasi Pribadi Pendaftaran alur kerja
Marketing Email API Saat Ini OAuth 2.0, Aplikasi Pribadi Kampanye email
Contacts API v1 Usang Kunci API (lama) Migrasi ke v3
Companies API v1 Usang Kunci API (lama) Migrasi ke v3

Penting: HubSpot menghentikan otentikasi kunci API dan beralih ke OAuth 2.0 serta aplikasi pribadi. Segera migrasikan semua integrasi.

Memulai: Pengaturan Otentikasi

Langkah 1: Buat Akun Pengembang HubSpot Anda

Sebelum mengakses API:

  1. Kunjungi Portal Pengembang HubSpot
  2. Masuk dengan akun HubSpot Anda (atau buat satu)
  3. Arahkan ke Aplikasi di dasbor pengembang
  4. Klik Buat aplikasi

Langkah 2: Pilih Metode Otentikasi

HubSpot mendukung dua metode otentikasi:

Metode Terbaik Untuk Tingkat Keamanan
OAuth 2.0 Aplikasi multi-tenant, integrasi publik Tinggi (token cakupan pengguna)
Aplikasi Pribadi Integrasi internal, portal tunggal Tinggi (token cakupan portal)

Langkah 3: Siapkan Aplikasi Pribadi (Direkomendasikan untuk Integrasi Internal)

Buat aplikasi pribadi untuk akses portal tunggal:

  1. Buka Pengaturan > Integrasi > Aplikasi Pribadi
  2. Klik Buat aplikasi pribadi
  3. Konfigurasi lingkup (scopes):
contacts
crm.objects.companies
crm.objects.deals
crm.objects.tickets
automation
webhooks
  1. Buat token akses
  2. Salin dan simpan dengan aman
# .env file
HUBSPOT_ACCESS_TOKEN="pat-na1-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
HUBSPOT_PORTAL_ID="12345678"

Langkah 4: Siapkan OAuth 2.0 (Untuk Aplikasi Multi-Tenant)

Konfigurasi OAuth untuk akses multi-portal:

  1. Buka Aplikasi > Buat aplikasi
  2. Konfigurasi pengaturan otentikasi:
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()}`;
};

Langkah 5: Tukar Kode untuk Token Akses

Tangani 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');
  }
});

Langkah 6: Segarkan Token Akses

Token akses kedaluwarsa setelah 6 jam:

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,
      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;
};

Langkah 7: Melakukan Panggilan API Terotentikasi

Buat klien API yang dapat digunakan kembali:

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');

Bekerja dengan Objek CRM

Membuat Kontak

Buat atau perbarui kontak:

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}`);

Properti Kontak

Properti Tipe Deskripsi
email String Email utama (pengidentifikasi unik)
firstname String Nama depan
lastname String Nama belakang
phone String Nomor telepon
company String Nama perusahaan
website String URL Situs Web
lifecyclestage Enum lead, marketingqualifiedlead, salesqualifiedlead, opportunity, customer, evangelist, subscriber
createdate DateTime Dihasilkan secara otomatis
lastmodifieddate DateTime Dihasilkan secara otomatis

Mendapatkan Kontak

Ambil kontak berdasarkan 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}`);

Mencari Kontak

Cari dengan filter:

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}`);
});

Operator Filter Pencarian

Operator Deskripsi Contoh
EQ Sama dengan company EQ 'Acme'
NEQ Tidak sama dengan lifecyclestage NEQ 'subscriber'
CONTAINS_TOKEN Mengandung email CONTAINS_TOKEN 'gmail'
NOT_CONTAINS_TOKEN Tidak mengandung email NOT_CONTAINS_TOKEN 'test'
GT Lebih besar dari createdate GT '2026-01-01'
LT Lebih kecil dari createdate LT '2026-12-31'
GTE Lebih besar atau sama dengan deal_amount GTE 10000
LTE Lebih kecil atau sama dengan deal_amount LTE 50000
HAS_PROPERTY Memiliki nilai phone HAS_PROPERTY
NOT_HAS_PROPERTY Nilai tidak ada phone NOT_HAS_PROPERTY

Membuat Perusahaan

Buat catatan perusahaan:

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'
});

Menghubungkan Objek

Hubungkan kontak ke perusahaan:

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');

Jenis Asosiasi

Asosiasi ID Tipe Arah
Kontak → Perusahaan 1 Kontak terkait dengan Perusahaan
Perusahaan → Kontak 1 Perusahaan memiliki Kontak terkait
Penawaran → Kontak 3 Penawaran terkait dengan Kontak
Penawaran → Perusahaan 5 Penawaran terkait dengan Perusahaan
Tiket → Kontak 16 Tiket terkait dengan Kontak
Tiket → Perusahaan 15 Tiket terkait dengan Perusahaan

Membuat Penawaran (Deal)

Buat peluang penjualan:

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 }] }) }
);

Tahap Penawaran (Pipeline Default)

Tahap Nilai Internal
Janji Temu Terjadwal appointmentscheduled
Memenuhi Syarat untuk Membeli qualifiedtobuy
Presentasi Terjadwal presentationscheduled
Pengambil Keputusan Setuju decisionmakerboughtin
Kontrak Terkirim contractsent
Ditutup Menang closedwon
Ditutup Kalah closedlost

Webhook

Mengonfigurasi Webhook

Siapkan webhook untuk notifikasi real-time:

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}`);

Jenis Event Webhook

Jenis Event Pemicu
contact.creation Kontak baru dibuat
contact.propertyChange Properti kontak diperbarui
contact.deletion Kontak dihapus
company.creation Perusahaan baru dibuat
company.propertyChange Properti perusahaan diperbarui
deal.creation Penawaran baru dibuat
deal.stageChange Tahap penawaran berubah
deal.propertyChange Properti penawaran diperbarui
ticket.creation Tiket baru dibuat
ticket.propertyChange Properti tiket diperbarui

Menangani Webhook

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')
  );
}

Pembatasan Laju (Rate Limiting)

Memahami Pembatasan Laju

HubSpot memberlakukan batasan laju berdasarkan tingkat langganan:

Tingkat Permintaan/Detik Permintaan/Hari
Gratis/Pemula 100 100.000
Profesional 200 500.000
Perusahaan 400 1.000.000

Melebihi batas akan menghasilkan respons HTTP 429 (Too Many Requests).

Header Batasan Laju

Header Deskripsi
X-HubSpot-RateLimit-Second-Limit Permintaan maks per detik
X-HubSpot-RateLimit-Second-Remaining Sisa permintaan detik ini
X-HubSpot-RateLimit-Second-Reset Detik hingga batas detik direset
X-HubSpot-RateLimit-Daily-Limit Permintaan maks per hari
X-HubSpot-RateLimit-Daily-Remaining Sisa permintaan hari ini
X-HubSpot-RateLimit-Daily-Reset Detik hingga batas harian direset

Menerapkan Penanganan Batasan Laju

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;
  }
}

Daftar Periksa Deployment Produksi

Sebelum tayang (go live):


Kasus Penggunaan Dunia Nyata

Sinkronisasi CRM

Perusahaan SaaS menyinkronkan data pelanggan:

Perutean Prospek

Agen pemasaran mengotomatiskan distribusi prospek:

Kesimpulan

HubSpot API menyediakan kemampuan CRM dan otomatisasi pemasaran yang komprehensif. Poin-poin penting:

tombol

Bagian FAQ

Bagaimana cara melakukan otentikasi dengan HubSpot API?

Gunakan OAuth 2.0 untuk aplikasi multi-tenant atau aplikasi pribadi untuk integrasi portal tunggal. Otentikasi kunci API sudah usang.

Apa saja batasan laju HubSpot?

Batasan laju berkisar dari 100 permintaan/detik (Gratis) hingga 400 permintaan/detik (Enterprise), dengan batas harian dari 100 ribu hingga 1 juta permintaan.

Bagaimana cara membuat kontak di HubSpot?

Lakukan permintaan POST ke /crm/v3/objects/contacts dengan properti termasuk email, nama depan, nama belakang, dan bidang kustom lainnya.

Bisakah saya membuat properti kustom?

Ya, gunakan API Properti untuk membuat bidang kustom untuk semua jenis objek.

Bagaimana cara kerja webhook di HubSpot?

Konfigurasi webhook di pengaturan aplikasi Anda. HubSpot akan mengirim permintaan POST ke endpoint Anda ketika event yang ditentukan terjadi.

Mengembangkan API dengan Apidog

Apidog adalah alat pengembangan API yang membantu Anda mengembangkan API dengan lebih mudah dan efisien.