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.
Was ist die HubSpot API?
HubSpot bietet eine RESTful API für den Zugriff auf CRM-Daten und Marketing-Automatisierungsfunktionen. Die API unterstützt:
- Kontakte, Unternehmen, Deals, Tickets und benutzerdefinierte Objekte
- Marketing-E-Mails und Landing Pages
- Vertriebs-Pipelines und -Sequenzen
- Service-Tickets und Konversationen
- Analysen und Berichterstattung
- Workflows und Automatisierung
- Dateien und Assets
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:
- Besuchen Sie das HubSpot Developer Portal
- Melden Sie sich mit Ihrem HubSpot-Konto an (oder erstellen Sie eines)
- Navigieren Sie zu Apps im Entwickler-Dashboard
- 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:
- Gehen Sie zu Einstellungen > Integrationen > Private Apps
- Klicken Sie auf Eine private App erstellen
- Bereiche konfigurieren:
contacts
crm.objects.companies
crm.objects.deals
crm.objects.tickets
automation
webhooks
- Zugriffs-Token generieren
- 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:
- Gehen Sie zu Apps > App erstellen
- 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:
- [ ] Private App oder OAuth 2.0 Authentifizierung verwenden
- [ ] Tokens sicher speichern (verschlüsselte Datenbank)
- [ ] Automatische Token-Aktualisierung implementieren
- [ ] Ratenbegrenzung und Anfragen-Warteschlange einrichten
- [ ] Webhook-Endpunkt mit HTTPS konfigurieren
- [ ] Umfassende Fehlerbehandlung implementieren
- [ ] Logging für alle API-Aufrufe hinzufügen
- [ ] Nutzung der Ratenbegrenzung überwachen
- [ ] Runbook für gängige Probleme erstellen
Anwendungsfälle aus der Praxis
CRM-Synchronisation
Ein SaaS-Unternehmen synchronisiert Kundendaten:
- Herausforderung: Manuelle Dateneingabe zwischen App und HubSpot
- Lösung: Echtzeit-Synchronisation über Webhooks und API
- Ergebnis: Keine manuelle Eingabe, 100% Datengenauigkeit
Lead-Routing
Eine Marketingagentur automatisiert die Lead-Verteilung:
- Herausforderung: Langsame Lead-Antwortzeiten
- Lösung: Webhook-gesteuertes Routing an Vertriebsmitarbeiter
- Ergebnis: 5 Minuten Reaktionszeit, 40% Conversion-Steigerung
Fazit
Die HubSpot API bietet umfassende CRM- und Marketing-Automatisierungsfunktionen. Die wichtigsten Erkenntnisse:
- Verwenden Sie OAuth 2.0 für Multi-Tenant-Apps, private Apps für interne Integrationen
- Ratenbegrenzungen variieren je nach Stufe (100-400 Anfragen/Sekunde)
- Webhooks ermöglichen Echtzeit-Synchronisation
- CRM-Objekte unterstützen Verknüpfungen und benutzerdefinierte Eigenschaften
- Apidog optimiert API-Tests und Teamzusammenarbeit
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.
