DEV Community

Cover image for Calendly API Integration: Entwickler-Leitfaden für Terminplanung
Emre Demir
Emre Demir

Posted on • Originally published at apidog.com

Calendly API Integration: Entwickler-Leitfaden für Terminplanung

Kurz gesagt

Die Calendly APIs ermöglichen die Automatisierung von Terminplanungsworkflows. Sie authentifizieren sich mit OAuth 2.0, greifen über api.calendly.com auf Ereignistypen und Buchungen zu und erhalten Echtzeit-Updates über Webhooks. Für Tests verwenden Sie Apidog, um Webhook-Nutzdaten zu validieren und Ihre Integration zu testen, ohne echte Buchungen zu erstellen.

Teste Apidog noch heute

Einleitung

Calendly verarbeitet monatlich Millionen von Besprechungen. Menschen nutzen es für Verkaufsgespräche, Support-Sitzungen, Beratungen und Interviews. Die API ermöglicht es Ihnen, diese Planungsfunktion in Ihre eigenen Apps zu integrieren.

Das gängige Muster: Sie möchten, dass Calendly-Buchungen Aktionen in Ihrem System auslösen. Ein Benutzer bucht eine Demo, und Ihr CRM wird aktualisiert. Eine Beratung wird vereinbart, und Sie senden einen Fragebogen. Eine Besprechung wird abgesagt, und Sie benachrichtigen Ihr Team.

Die API von Calendly erledigt dies über Webhooks. Wenn Ereignisse eintreten (Buchung erstellt, abgesagt, verschoben), sendet Calendly POST-Anfragen an Ihre Endpunkte. Sie verarbeiten die Nutzdaten und ergreifen Maßnahmen.

💡 Tipp: Wenn Sie Planungs-Integrationen entwickeln, hilft Ihnen Apidog beim Testen von Webhook-Handlern und Validieren von Nutzdaten. Sie können Calendlys Antworten während der Entwicklung simulieren und sicherstellen, dass Ihre Integration alle Ereignistypen verarbeitet, bevor Sie sie mit echten Kalendern verbinden.

Authentifizierung mit OAuth 2.0

Calendly verwendet OAuth 2.0 für den API-Zugriff. Sie können nicht einfach einen API-Schlüssel verwenden.

Eine OAuth-Anwendung erstellen

  1. Gehen Sie zu Calendly → Integrationen → API & Webhooks
  2. Klicken Sie auf „Neue Anwendung erstellen“
  3. Legen Sie Ihre Umleitungs-URI fest (z.B. https://yourapp.com/auth/calendly/callback)
  4. Rufen Sie Ihre Client-ID und Ihr Client-Geheimnis ab

Der OAuth-Fluss

Schritt 1: Benutzer zur Autorisierung umleiten

https://auth.calendly.com/oauth/authorize?
  client_id=YOUR_CLIENT_ID&
  response_type=code&
  redirect_uri=https://yourapp.com/auth/calendly/callback
Enter fullscreen mode Exit fullscreen mode

Schritt 2: Benutzer autorisiert und wird zurückgeleitet

https://yourapp.com/auth/calendly/callback?code=AUTHORIZATION_CODE
Enter fullscreen mode Exit fullscreen mode

Schritt 3: Code gegen Zugriffstoken tauschen

const response = await fetch('https://auth.calendly.com/oauth/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': 'Basic ' + Buffer.from(clientId + ':' + clientSecret).toString('base64')
  },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: authCode,
    redirect_uri: 'https://yourapp.com/auth/calendly/callback'
  })
})

const { access_token, refresh_token, expires_in } = await response.json()
Enter fullscreen mode Exit fullscreen mode

Schritt 4: Das Token verwenden

curl -X GET "https://api.calendly.com/users/me" \
  -H "Authorization: Bearer ACCESS_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Tokens aktualisieren

Zugriffstoken verfallen nach 2 Stunden. Verwenden Sie Refresh-Tokens, um neue zu erhalten:

const response = await fetch('https://auth.calendly.com/oauth/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': 'Basic ' + Buffer.from(clientId + ':' + clientSecret).toString('base64')
  },
  body: new URLSearchParams({
    grant_type: 'refresh_token',
    refresh_token: storedRefreshToken
  })
})
Enter fullscreen mode Exit fullscreen mode

Benutzerinformationen abrufen

Aktuellen Benutzer abrufen

curl -X GET "https://api.calendly.com/users/me" \
  -H "Authorization: Bearer ACCESS_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Antwort:

{
  "resource": {
    "avatar_url": "https://calendly.com/avatar.jpg",
    "created_at": "2024-01-15T10:00:00Z",
    "current_organization": "https://api.calendly.com/organizations/ABC123",
    "email": "you@example.com",
    "name": "John Doe",
    "scheduling_url": "https://calendly.com/johndoe",
    "slug": "johndoe",
    "timezone": "America/New_York",
    "uri": "https://api.calendly.com/users/ABC123"
  }
}
Enter fullscreen mode Exit fullscreen mode

Organisationsmitgliedschaft abrufen

curl -X GET "https://api.calendly.com/organization_memberships/me" \
  -H "Authorization: Bearer ACCESS_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Ereignistypen

Ereignistypen sind die Besprechungsvorlagen, die Benutzer erstellen (30-minütiger Anruf, 60-minütige Beratung usw.).

Ereignistypen auflisten

curl -X GET "https://api.calendly.com/event_types?user=https://api.calendly.com/users/ABC123" \
  -H "Authorization: Bearer ACCESS_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Antwort:

{
  "resource": {
    "uri": "https://api.calendly.com/event_types/ETC123",
    "active": true,
    "booking_method": "instant",
    "color": "#0066FF",
    "created_at": "2024-01-15T10:00:00Z",
    "description_html": "<p>30-minute consultation</p>",
    "duration": 30,
    "internal_note": "Use Zoom link",
    "kind": "solo",
    "name": "30 Min Consultation",
    "pooling_type": null,
    "profile": {
      "name": "John Doe",
      "type": "User",
      "owner": "https://api.calendly.com/users/ABC123"
    },
    "scheduling_url": "https://calendly.com/johndoe/30min",
    "slug": "30min",
    "type": "StandardEventType"
  },
  "pagination": {
    "count": 1,
    "next_page": null
  }
}
Enter fullscreen mode Exit fullscreen mode

Einen bestimmten Ereignistyp abrufen

curl -X GET "https://api.calendly.com/event_types/ETC123" \
  -H "Authorization: Bearer ACCESS_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Geplante Ereignisse (Buchungen)

Ereignisse sind die tatsächlichen Buchungen, die über Calendly vorgenommen werden.

Geplante Ereignisse auflisten

curl -X GET "https://api.calendly.com/scheduled_events?user=https://api.calendly.com/users/ABC123" \
  -H "Authorization: Bearer ACCESS_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Nach Datumsbereich filtern:

curl -X GET "https://api.calendly.com/scheduled_events?min_start_time=2026-03-01T00:00:00Z&max_start_time=2026-03-31T23:59:59Z" \
  -H "Authorization: Bearer ACCESS_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Antwort:

{
  "resource": {
    "uri": "https://api.calendly.com/scheduled_events/ABC123",
    "status": "active",
    "tracking": {
      "utm_campaign": "spring_sale",
      "utm_source": "email",
      "utm_medium": "newsletter"
    },
    "created_at": "2026-03-24T10:00:00Z",
    "end_time": "2026-03-25T11:00:00Z",
    "event_type": "https://api.calendly.com/event_types/ETC123",
    "invitees_counter": {
      "active": 1,
      "limit": 1,
      "total": 1
    },
    "location": {
      "type": "zoom",
      "join_url": "https://zoom.us/j/123456789"
    },
    "start_time": "2026-03-25T10:30:00Z",
    "updated_at": "2026-03-24T10:00:00Z"
  }
}
Enter fullscreen mode Exit fullscreen mode

Ereignisdetails abrufen

curl -X GET "https://api.calendly.com/scheduled_events/EVENT_ID" \
  -H "Authorization: Bearer ACCESS_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Teilnehmer für ein Ereignis abrufen

curl -X GET "https://api.calendly.com/scheduled_events/EVENT_ID/invitees" \
  -H "Authorization: Bearer ACCESS_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Antwort:

{
  "resource": [
    {
      "cancel_url": "https://calendly.com/cancellations/ABC123",
      "created_at": "2026-03-24T10:00:00Z",
      "email": "jane@example.com",
      "event": "https://api.calendly.com/scheduled_events/ABC123",
      "name": "Jane Smith",
      "new_invitee": null,
      "old_invitee": null,
      "reschedule_url": "https://calendly.com/reschedulings/ABC123",
      "status": "active",
      "text_reminder_number": "+15551234567",
      "timezone": "America/New_York",
      "tracking": {
        "utm_campaign": null,
        "utm_source": null
      },
      "updated_at": "2026-03-24T10:00:00Z",
      "uri": "https://api.calendly.com/scheduled_event_invitees/INV123",
      "canceled": null
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Webhooks für Echtzeit-Updates

Webhooks benachrichtigen Ihre App in Echtzeit über Buchungsereignisse.

Ein Webhook-Abonnement erstellen

curl -X POST "https://api.calendly.com/webhook_subscriptions" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type": "application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/calendly",
    "events": [
      "invitee.created",
      "invitee.canceled",
      "invitee.rescheduled"
    ],
    "organization": "https://api.calendly.com/organizations/ORG123",
    "scope": "organization"
  }'
Enter fullscreen mode Exit fullscreen mode

Verfügbare Ereignisse:

  • invitee.created – Neue Buchung erstellt
  • invitee.canceled – Buchung storniert
  • invitee.rescheduled – Buchung verschoben

Webhook-Abonnements auflisten

curl -X GET "https://api.calendly.com/webhook_subscriptions?organization=https://api.calendly.com/organizations/ORG123" \
  -H "Authorization: Bearer ACCESS_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Einen Webhook löschen

curl -X DELETE "https://api.calendly.com/webhook_subscriptions/WEBHOOK_ID" \
  -H "Authorization: Bearer ACCESS_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Webhook-Nutzdaten verarbeiten

Webhook-Signaturen überprüfen

Calendly signiert Webhooks mit einer Signatur im Header Calendly-Webhook-Signature:

import crypto from 'crypto'

function verifySignature(payload, signature, secret) {
  const [t, v1] = signature.split(',')
  const timestamp = t.split('=')[1]
  const hash = v1.split('=')[1]

  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(timestamp + '.' + payload)
    .digest('hex')

  return crypto.timingSafeEqual(
    Buffer.from(hash),
    Buffer.from(expectedSignature)
  )
}

app.post('/webhooks/calendly', (req, res) => {
  const signature = req.headers['calendly-webhook-signature']
  const payload = JSON.stringify(req.body)

  if (!verifySignature(payload, signature, process.env.CALENDLY_WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature')
  }

  // Webhook verarbeiten
  handleWebhook(req.body)
  res.status(200).send('OK')
})
Enter fullscreen mode Exit fullscreen mode

Buchungsereignisse verarbeiten

function handleWebhook(payload) {
  const { event, payload: data } = payload

  switch (event) {
    case 'invitee.created':
      console.log(`Neue Buchung: ${data.event.start_time}`)
      console.log(`Eingeladener: ${data.email}`)
      // Zu CRM hinzufügen, Bestätigungs-E-Mail senden usw.
      syncToCRM(data)
      break

    case 'invitee.canceled':
      console.log(`Buchung storniert: ${data.event.uri}`)
      // CRM aktualisieren, Team benachrichtigen usw.
      removeFromCRM(data)
      break

    case 'invitee.rescheduled':
      console.log(`Buchung verschoben: ${data.event.start_time}`)
      // Kalender aktualisieren, Team benachrichtigen usw.
      updateCRM(data)
      break
  }
}
Enter fullscreen mode Exit fullscreen mode

Testen mit Apidog

Die Calendly API erfordert OAuth, was das Testen erschwert. Apidog vereinfacht dies.

Image showing Apidog interface for testing APIs

1. OAuth-Antworten simulieren

Während der Entwicklung müssen Sie nicht jedes Mal den vollständigen OAuth-Fluss durchlaufen. Simulieren Sie die Token-Antwort:

{
  "access_token": "mock_access_token",
  "refresh_token": "mock_refresh_token",
  "expires_in": 7200,
  "created_at": 1700000000
}
Enter fullscreen mode Exit fullscreen mode

2. Webhook-Handler testen

Simulieren Sie Webhook-Nutzdaten:

{
  "created_at": "2026-03-24T10:00:00Z",
  "event": "invitee.created",
  "payload": {
    "email": "test@example.com",
    "name": "Test User",
    "event": {
      "start_time": "2026-03-25T10:30:00Z",
      "end_time": "2026-03-25T11:00:00Z",
      "event_type": {
        "name": "30 Min Consultation"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Senden Sie an Ihren Webhook-Endpunkt und überprüfen Sie die Verarbeitung.

3. Umgebungsvariablen

CALENDLY_CLIENT_ID: abc123
CALENDLY_CLIENT_SECRET: xyz789
CALENDLY_ACCESS_TOKEN: stored_token
CALENDLY_REFRESH_TOKEN: stored_refresh
CALENDLY_WEBHOOK_SECRET: webhook_signing_secret
Enter fullscreen mode Exit fullscreen mode

4. Webhook-Signaturen validieren

pm.test('Webhook signature is valid', () => {
  const signature = pm.request.headers.get('Calendly-Webhook-Signature')
  pm.expect(signature).to.exist

  const payload = pm.request.body.raw
  const secret = pm.environment.get('CALENDLY_WEBHOOK_SECRET')

  // Signatur überprüfen
  const valid = verifySignature(payload, signature, secret)
  pm.expect(valid).to.be.true
})
Enter fullscreen mode Exit fullscreen mode

Testen Sie Calendly-Webhooks mit Apidog – kostenlos.

Häufige Fehler und Behebungen

401 Nicht autorisiert

Ursache: Ungültiges oder abgelaufenes Token.

Behebung:

  1. Überprüfen Sie, ob das Token nicht abgelaufen ist (2 Stunden Gültigkeit).
  2. Verwenden Sie ein Refresh-Token, um ein neues Zugriffstoken zu erhalten.
  3. Stellen Sie sicher, dass der Authorization-Header Bearer {token} lautet.

403 Verboten

Ursache: OAuth-Bereich unzureichend.

Behebung: Das OAuth-Token benötigt entsprechende Berechtigungen (Scopes). Fügen Sie bei der Anforderung der Autorisierung die benötigten Scopes hinzu. Calendlys Scopes sind implizit, basierend auf dem, was der Benutzer autorisiert.

404 Nicht gefunden

Ursache: Ressource existiert nicht oder Benutzer hat keinen Zugriff.

Behebung:

  1. Überprüfen Sie, ob die Ressourcen-URI korrekt ist.
  2. Stellen Sie sicher, dass der authentifizierte Benutzer Zugriff auf die Ressource hat.
  3. Überprüfen Sie, ob der Ereignistyp oder die Ereignis-ID gültig ist.

422 Unverarbeitbare Entität

Ursache: Validierungsfehler in der Anfrage.

Behebung: Überprüfen Sie die Antwort auf Details:

{
  "title": "Validation Error",
  "message": "Invalid parameter: url must be a valid HTTPS URL"
}
Enter fullscreen mode Exit fullscreen mode

Alternativen und Vergleiche

Funktion Calendly Acuity Cal.com Calendly
Kostenlose Stufe Eingeschränkt Eingeschränkt Selbst gehostet kostenlos
API-Zugriff
Webhooks
OAuth API-Schlüssel API-Schlüssel OAuth
Teamplanung
Open Source Nein Nein Ja Nein

Calendly verfügt über die ausgereifteste API-Dokumentation und den ausgereiftesten OAuth-Fluss. Cal.com ist die Open-Source-Alternative mit einfacherer API-Schlüssel-Authentifizierung.

Anwendungsfälle aus der Praxis

Integration mit dem Vertriebs-CRM.

Ein B2B-SaaS-Unternehmen bettet Calendly auf seiner Preisseite ein. Wenn jemand eine Demo bucht, löst der Webhook Folgendes aus:

  1. Lead in Salesforce erstellen
  2. Slack-Benachrichtigung an das Vertriebsteam senden
  3. Zur Marketing-Automatisierungssequenz hinzufügen
  4. Aktivität in der Customer-Success-Plattform protokollieren

Beratungsplattform.

Eine Plattform für Rechtsdienstleistungen ermöglicht es Klienten, Beratungen mit Anwälten zu buchen. Die API-Integration:

  1. Synchronisiert Buchungen mit dem internen Planungssystem
  2. Erzeugt Zoom-Besprechungslinks
  3. Sendet 24 Stunden vorher einen Aufnahmefragebogen
  4. Erstellt eine Fallakte, wenn die Besprechung abgeschlossen ist

Interviewplanung.

Eine Recruiting-Plattform verwendet Calendly für Kandidateninterviews. Webhooks:

  1. ATS mit Interviewdetails aktualisieren
  2. Personalchef per E-Mail benachrichtigen
  3. Kalendereinladungen an alle Teilnehmer senden
  4. Nichterscheinen zur Nachverfolgung erfassen

Fazit

Das haben Sie gelernt:

  • Calendly verwendet OAuth 2.0 zur API-Authentifizierung
  • Zugriff auf Ereignistypen und geplante Ereignisse über die API
  • Webhooks bieten Echtzeit-Benachrichtigungen über Buchungen
  • Überprüfen Sie Webhook-Signaturen immer aus Sicherheitsgründen
  • Testen Sie mit Apidog, bevor Sie eine Verbindung zu echten Kalendern herstellen

Ihre nächsten Schritte:

  1. Eine OAuth-Anwendung in Calendly erstellen
  2. Den OAuth-Fluss implementieren
  3. Ein Webhook-Abonnement einrichten
  4. Mit simulierten Nutzdaten in Apidog testen
  5. In Produktion bereitstellen

Testen Sie Calendly-Webhooks mit Apidog – kostenlos.

FAQ

Benötige ich einen kostenpflichtigen Calendly-Plan, um die API zu nutzen?

Nein. Die API ist in allen Plänen, einschließlich des kostenlosen, verfügbar. Kostenlose Pläne haben jedoch eingeschränkte Funktionen. Webhooks sind in allen Plänen verfügbar.

Was ist der Unterschied zwischen Webhooks auf Benutzerebene und auf Organisationsebene?

Webhooks auf Benutzerebene erfassen nur Ereignisse für einen Benutzer. Webhooks auf Organisationsebene erfassen Ereignisse für alle Teammitglieder. Die meisten Integrationen verwenden den Organisationsbereich.

Wie erhalte ich das Webhook-Signaturgeheimnis?

Wenn Sie einen Webhook über die API erstellen, enthält die Antwort einen signing_key. Speichern Sie diesen sicher. Er wird zur Überprüfung von Webhook-Signaturen verwendet.

Kann ich Buchungen über die API erstellen?

Nein. Calendly hat keinen API-Endpunkt zum Erstellen von Buchungen. Buchungen müssen über die Benutzeroberfläche von Calendly oder eingebettete Widgets erfolgen. Die API ist für Buchungen nur lesend.

Wie gehe ich mit Zeitzonenumrechnungen um?

Alle Zeitstempel in der API sind UTC (ISO 8601). Konvertieren Sie sie in Ihrer Anwendung in die lokale Zeit. Die Zeitzone des Benutzers ist in der Benutzerressource verfügbar.

Wie hoch ist das Ratenlimit?

Calendly dokumentiert Ratenlimits nicht öffentlich. Verwenden Sie angemessene Anfragemuster. Wenn Sie Limits erreichen, implementieren Sie exponentielles Backoff.

Kann ich historische Buchungen abrufen?

Ja. Verwenden Sie min_start_time und max_start_time, um historische Ereignisse abzufragen. Es gibt keine Begrenzung, wie weit zurück Sie abfragen können.

Wie teste ich den OAuth-Fluss lokal?

Verwenden Sie einen Tunneldienst wie ngrok, um Ihren lokalen Server freizulegen. Legen Sie die Umleitungs-URI auf Ihre ngrok-URL fest. Schließen Sie den OAuth-Fluss in einem Browser ab und überprüfen Sie dann den Callback.

Top comments (0)