HubSpot API Nutzung 2026: Anleitung & Tutorial

Ashley Innocent

Ashley Innocent

25 March 2026

HubSpot API Nutzung 2026: Anleitung & Tutorial

TL;DR

Die HubSpot API ermöglicht Entwicklern die programmatische Integration mit CRM-, Marketing-, Vertriebs- und Service-Hubs. Sie nutzt OAuth 2.0 und die Authentifizierung privater Apps, RESTful-Endpunkte für Kontakte, Unternehmen, Deals, Tickets und mehr, mit Ratenbegrenzungen, die auf der Abonnementstufe basieren. Dieser Leitfaden behandelt die Authentifizierungseinrichtung, Kern-Endpunkte, Webhooks und Strategien für die Produktionsintegration.

Einführung

HubSpot verwaltet über 194.000 Kundenkonten und Milliarden von CRM-Datensätzen. Für Entwickler, die CRM-Integrationen, Marketing-Automatisierung oder Vertriebstools entwickeln, ist die HubSpot API-Integration keine Option – sie ist unerlässlich, um über 7 Millionen Nutzer zu erreichen.

Hier ist die Realität: Unternehmen verlieren wöchentlich 15-20 Stunden durch manuelle Dateneingabe zwischen Systemen. Eine solide HubSpot API-Integration automatisiert die Kontaktsynchronisation, Deal-Updates, Marketing-Workflows und Berichterstellung über verschiedene Plattformen hinweg.

💡
Apidog vereinfacht das Testen von API-Integrationen. Testen Sie Ihre HubSpot-Endpunkte, validieren Sie OAuth-Flows, inspizieren Sie Webhook-Nutzdaten und debuggen Sie Authentifizierungsprobleme in einem einzigen Arbeitsbereich. Importieren Sie API-Spezifikationen, mocken Sie Antworten und teilen Sie Testszenarien mit Ihrem Team.
Button

Was ist die HubSpot API?

HubSpot bietet eine RESTful API für den Zugriff auf CRM-Daten und Marketing-Automatisierungsfunktionen. Die API unterstützt:

Hauptfunktionen

Funktion Beschreibung
RESTful Design Standard-HTTP-Methoden mit JSON-Antworten
OAuth 2.0 + Private Apps Flexible Authentifizierungsoptionen
Webhooks Echtzeit-Benachrichtigungen für Objektänderungen
Ratenbegrenzung Tierbasierte Limits (100-400 Anfragen/Sekunde)
CRM-Objekte Unterstützung für Standard- und benutzerdefinierte Objekte
Verknüpfungen Objekte miteinander verknüpfen (Kontakt-Unternehmen, Deal-Kontakt)
Eigenschaften Benutzerdefinierte Felder für jeden Objekttyp
Such-API Komplexe Filterung und Sortierung

API-Architekturübersicht

HubSpot verwendet versionierte REST-APIs:

https://api.hubapi.com/

API-Versionen im Vergleich

Version Status Authentifizierung Anwendungsfall
CRM API v3 Aktuell OAuth 2.0, Private App Alle neuen Integrationen
Automatisierungs-API v4 Aktuell OAuth 2.0, Private App Workflow-Einschreibung
Marketing-E-Mail-API Aktuell OAuth 2.0, Private App E-Mail-Kampagnen
Kontakte-API v1 Veraltet API-Schlüssel (veraltet) Zu v3 migrieren
Unternehmen-API v1 Veraltet API-Schlüssel (veraltet) Zu v3 migrieren

Wichtig: HubSpot hat die API-Schlüssel-Authentifizierung zugunsten von OAuth 2.0 und privaten Apps eingestellt. Migrieren Sie alle Integrationen sofort.

Erste Schritte: Authentifizierungseinrichtung

Schritt 1: Erstellen Sie Ihr HubSpot-Entwicklerkonto

Vor dem Zugriff auf die API:

  1. Besuchen Sie das HubSpot Developer Portal
  2. Melden Sie sich mit Ihrem HubSpot-Konto an (oder erstellen Sie eines)
  3. Navigieren Sie zu Apps im Entwickler-Dashboard
  4. Klicken Sie auf App erstellen

Schritt 2: Wählen Sie die Authentifizierungsmethode

HubSpot unterstützt zwei Authentifizierungsmethoden:

Methode Am besten geeignet für Sicherheitsstufe
OAuth 2.0 Multi-Tenant-Apps, öffentliche Integrationen Hoch (benutzerbezogene Tokens)
Private App Interne Integrationen, einzelnes Portal Hoch (portalbezogener Token)

Schritt 3: Private App einrichten (Empfohlen für interne Integrationen)

Erstellen Sie eine private App für den Zugriff auf ein einzelnes Portal:

  1. Gehen Sie zu Einstellungen > Integrationen > Private Apps
  2. Klicken Sie auf Eine private App erstellen
  3. Bereiche konfigurieren:
contacts
crm.objects.companies
crm.objects.deals
crm.objects.tickets
automation
webhooks
  1. Zugriffs-Token generieren
  2. Kopieren und sicher speichern
# .env file
HUBSPOT_ACCESS_TOKEN="pat-na1-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
HUBSPOT_PORTAL_ID="12345678"

Schritt 4: OAuth 2.0 einrichten (Für Multi-Tenant-Apps)

OAuth für Multi-Portal-Zugriff konfigurieren:

  1. Gehen Sie zu Apps > App erstellen
  2. Authentifizierungseinstellungen konfigurieren:
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()}`;
};

Schritt 5: Code gegen Zugriffs-Token austauschen

OAuth-Callback behandeln:

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

Schritt 6: Zugriffs-Token aktualisieren

Zugriffs-Tokens verfallen nach 6 Stunden:

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

Schritt 7: Authentifizierte API-Aufrufe tätigen

Wiederverwendbaren API-Client erstellen:

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

Arbeiten mit CRM-Objekten

Einen Kontakt erstellen

Einen Kontakt erstellen oder aktualisieren:

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(`Kontakt erstellt: ${contact.id}`);

Kontakteigenschaften

Eigenschaft Typ Beschreibung
email String Primäre E-Mail (eindeutiger Identifikator)
firstname String Vorname
lastname String Nachname
phone String Telefonnummer
company String Firmenname
website String Website-URL
lifecyclestage Enum Lead, Marketing Qualified Lead, Sales Qualified Lead, Opportunity, Kunde, Evangelist, Abonnent
createdate DateTime Automatisch generiert
lastmodifieddate DateTime Automatisch generiert

Einen Kontakt abrufen

Kontakt per ID abrufen:

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(`E-Mail: ${contact.properties.email}`);

Kontakte suchen

Mit Filtern suchen:

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

Suchfilter-Operatoren

Operator Beschreibung Beispiel
EQ Gleich company EQ 'Acme'
NEQ Nicht gleich lifecyclestage NEQ 'subscriber'
CONTAINS_TOKEN Enthält email CONTAINS_TOKEN 'gmail'
NOT_CONTAINS_TOKEN Enthält nicht email NOT_CONTAINS_TOKEN 'test'
GT Größer als createdate GT '2026-01-01'
LT Kleiner als createdate LT '2026-12-31'
GTE Größer oder gleich deal_amount GTE 10000
LTE Kleiner oder gleich deal_amount LTE 50000
HAS_PROPERTY Hat Wert phone HAS_PROPERTY
NOT_HAS_PROPERTY Fehlender Wert phone NOT_HAS_PROPERTY

Ein Unternehmen erstellen

Unternehmensdatensatz erstellen:

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

Objekte verknüpfen

Kontakte mit Unternehmen verknüpfen:

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

Verknüpfungstypen

Verknüpfung Typ-ID Richtung
Kontakt → Unternehmen 1 Kontakt ist mit Unternehmen verknüpft
Unternehmen → Kontakt 1 Unternehmen hat verknüpften Kontakt
Deal → Kontakt 3 Deal ist mit Kontakt verknüpft
Deal → Unternehmen 5 Deal ist mit Unternehmen verknüpft
Ticket → Kontakt 16 Ticket ist mit Kontakt verknüpft
Ticket → Unternehmen 15 Ticket ist mit Unternehmen verknüpft

Einen Deal erstellen

Vertriebschance erstellen:

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

Deal-Phasen (Standard-Pipeline)

Phase Interner Wert
Termine vereinbart appointmentscheduled
Kaufinteressent qualifiziert qualifiedtobuy
Präsentation geplant presentationscheduled
Entscheidungsträger überzeugt decisionmakerboughtin
Vertrag versendet contractsent
Abschluss gewonnen closedwon
Abschluss verloren closedlost

Webhooks

Webhooks konfigurieren

Webhooks für Echtzeit-Benachrichtigungen einrichten:

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 erstellt: ${webhook.id}`);

Webhook-Ereignistypen

Ereignistyp Auslöser
contact.creation Neuer Kontakt erstellt
contact.propertyChange Kontakteigenschaft aktualisiert
contact.deletion Kontakt gelöscht
company.creation Neues Unternehmen erstellt
company.propertyChange Unternehmenseigenschaft aktualisiert
deal.creation Neuer Deal erstellt
deal.stageChange Deal-Phase geändert
deal.propertyChange Deal-Eigenschaft aktualisiert
ticket.creation Neues Ticket erstellt
ticket.propertyChange Ticket-Eigenschaft aktualisiert

Webhooks verarbeiten

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('Ungültige Webhook-Signatur');
    return res.status(401).send('Nicht autorisiert');
  }

  const events = req.body;

  for (const event of events) {
    console.log(`Ereignis: ${event.eventType}`);
    console.log(`Objekt: ${event.objectType} - ${event.objectId}`);
    console.log(`Eigenschaft: ${event.propertyName}`);
    console.log(`Wert: ${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')
  );
}

Ratenbegrenzung

Ratenbegrenzungen verstehen

HubSpot erzwingt Ratenbegrenzungen basierend auf der Abonnementstufe:

Stufe Anfragen/Sekunde Anfragen/Tag
Kostenlos/Starter 100 100.000
Professional 200 500.000
Enterprise 400 1.000.000

Eine Überschreitung der Limits führt zu HTTP 429 (Too Many Requests) Antworten.

Ratenbegrenzungs-Header

Header Beschreibung
X-HubSpot-RateLimit-Second-Limit Maximale Anfragen pro Sekunde
X-HubSpot-RateLimit-Second-Remaining Verbleibende Anfragen in dieser Sekunde
X-HubSpot-RateLimit-Second-Reset Sekunden bis zur Zurücksetzung des Sekundenlimits
X-HubSpot-RateLimit-Daily-Limit Maximale Anfragen pro Tag
X-HubSpot-RateLimit-Daily-Remaining Verbleibende Anfragen heute
X-HubSpot-RateLimit-Daily-Reset Sekunden bis zur Zurücksetzung des Tageslimits

Implementierung der Ratenbegrenzungsbehandlung

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(`Wenig verbleibende Ratenbegrenzung: ${remaining}`);
      }

      return response;
    } catch (error) {
      if (error.message.includes('429') && attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000;
        console.log(`Ratenbegrenzt. Erneuter Versuch 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;
  }
}

Checkliste für die Produktionsbereitstellung

Vor dem Live-Gang:


Anwendungsfälle aus der Praxis

CRM-Synchronisation

Ein SaaS-Unternehmen synchronisiert Kundendaten:

Lead-Routing

Eine Marketingagentur automatisiert die Lead-Verteilung:

Fazit

Die HubSpot API bietet umfassende CRM- und Marketing-Automatisierungsfunktionen. Die wichtigsten Erkenntnisse:

Button

FAQ-Bereich

Wie authentifiziere ich mich mit der HubSpot API?

Verwenden Sie OAuth 2.0 für Multi-Tenant-Apps oder private Apps für Single-Portal-Integrationen. Die API-Schlüssel-Authentifizierung ist veraltet.

Was sind die HubSpot Ratenbegrenzungen?

Die Ratenbegrenzungen reichen von 100 Anfragen/Sekunde (Kostenlos) bis 400 Anfragen/Sekunde (Enterprise), mit täglichen Limits von 100.000 bis 1 Million Anfragen.

Wie erstelle ich einen Kontakt in HubSpot?

POST an /crm/v3/objects/contacts mit Eigenschaften wie E-Mail, Vorname, Nachname und allen benutzerdefinierten Feldern.

Kann ich benutzerdefinierte Eigenschaften erstellen?

Ja, verwenden Sie die Properties API, um benutzerdefinierte Felder für jeden Objekttyp zu erstellen.

Wie funktionieren Webhooks in HubSpot?

Konfigurieren Sie Webhooks in Ihren App-Einstellungen. HubSpot sendet POST-Anfragen an Ihren Endpunkt, wenn bestimmte Ereignisse auftreten.

Praktizieren Sie API Design-First in Apidog

Entdecken Sie eine einfachere Möglichkeit, APIs zu erstellen und zu nutzen