En bref
Les API Calendly vous permettent d'automatiser les flux de travail de planification. Vous vous authentifiez avec OAuth 2.0, accédez aux types d'événements et aux réservations via api.calendly.com, et recevez des mises à jour en temps réel via des webhooks. Pour les tests, utilisez Apidog pour valider les charges utiles des webhooks et tester votre intégration sans créer de réservations réelles.
Introduction
Calendly traite des millions de réunions chaque mois. Les gens l'utilisent pour les appels de vente, les sessions de support, les consultations et les entretiens. L'API vous permet d'intégrer cette puissance de planification dans vos propres applications.
Le schéma courant : vous souhaitez que les réservations Calendly déclenchent des actions dans votre système. Un utilisateur réserve une démo, et votre CRM est mis à jour. Une consultation est planifiée, et vous envoyez un questionnaire. Une réunion est annulée, et vous informez votre équipe.
L'API de Calendly gère cela via des webhooks. Lorsque des événements se produisent (réservation créée, annulée, reprogrammée), Calendly effectue une requête POST vers vos points d'extrémité. Vous traitez la charge utile et agissez en conséquence.
Authentification avec OAuth 2.0
Calendly utilise OAuth 2.0 pour l'accès à l'API. Vous ne pouvez pas simplement utiliser une clé API.
Créer une application OAuth
- Allez dans Calendly → Intégrations → API & Webhooks
- Cliquez sur "Créer une nouvelle application"
- Définissez votre URI de redirection (par exemple,
https://yourapp.com/auth/calendly/callback) - Obtenez votre ID client et votre secret client
Le flux OAuth
Étape 1 : Rediriger l'utilisateur pour l'autorisation
https://auth.calendly.com/oauth/authorize?
client_id=VOTRE_ID_CLIENT&
response_type=code&
redirect_uri=https://yourapp.com/auth/calendly/callback
Étape 2 : L'utilisateur autorise et est redirigé
https://yourapp.com/auth/calendly/callback?code=CODE_D_AUTORISATION
Étape 3 : Échanger le code contre un jeton d'accès
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()
Étape 4 : Utiliser le jeton
curl -X GET "https://api.calendly.com/users/me" \
-H "Authorization: Bearer JETON_D_ACCES"
Jetons d'actualisation
Les jetons d'accès expirent après 2 heures. Utilisez les jetons d'actualisation pour en obtenir de nouveaux :
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
})
})
Obtention des informations utilisateur
Obtenir l'utilisateur actuel
curl -X GET "https://api.calendly.com/users/me" \
-H "Authorization: Bearer JETON_D_ACCES"
Réponse :
{
"resource": {
"avatar_url": "https://calendly.com/avatar.jpg",
"created_at": "2024-01-15T10:00:00Z",
"current_organization": "https://api.calendly.com/organizations/ABC123",
"email": "vous@exemple.com",
"name": "Jean Dupont",
"scheduling_url": "https://calendly.com/jeandupont",
"slug": "jeandupont",
"timezone": "America/New_York",
"uri": "https://api.calendly.com/users/ABC123"
}
}
Obtenir l'adhésion à l'organisation
curl -X GET "https://api.calendly.com/organization_memberships/me" \
-H "Authorization: Bearer JETON_D_ACCES"
Types d'événements
Les types d'événements sont les modèles de réunion que les utilisateurs créent (appel de 30 min, consultation de 60 min, etc.).
Lister les types d'événements
curl -X GET "https://api.calendly.com/event_types?user=https://api.calendly.com/users/ABC123" \
-H "Authorization: Bearer JETON_D_ACCES"
Réponse :
{
"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>Consultation de 30 minutes</p>",
"duration": 30,
"internal_note": "Utiliser le lien Zoom",
"kind": "solo",
"name": "Consultation de 30 min",
"pooling_type": null,
"profile": {
"name": "Jean Dupont",
"type": "User",
"owner": "https://api.calendly.com/users/ABC123"
},
"scheduling_url": "https://calendly.com/jeandupont/30min",
"slug": "30min",
"type": "StandardEventType"
},
"pagination": {
"count": 1,
"next_page": null
}
}
Obtenir un type d'événement spécifique
curl -X GET "https://api.calendly.com/event_types/ETC123" \
-H "Authorization: Bearer JETON_D_ACCES"
Événements planifiés (réservations)
Les événements sont les réservations réelles effectuées via Calendly.
Lister les événements planifiés
curl -X GET "https://api.calendly.com/scheduled_events?user=https://api.calendly.com/users/ABC123" \
-H "Authorization: Bearer JETON_D_ACCES"
Filtrer par plage de dates :
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 JETON_D_ACCES"
Réponse :
{
"resource": {
"uri": "https://api.calendly.com/scheduled_events/ABC123",
"status": "active",
"tracking": {
"utm_campaign": "vente_printemps",
"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"
}
}
Obtenir les détails de l'événement
curl -X GET "https://api.calendly.com/scheduled_events/ID_EVENEMENT" \
-H "Authorization: Bearer JETON_D_ACCES"
Obtenir les invités pour un événement
curl -X GET "https://api.calendly.com/scheduled_events/ID_EVENEMENT/invitees" \
-H "Authorization: Bearer JETON_D_ACCES"
Réponse :
{
"resource": [
{
"cancel_url": "https://calendly.com/cancellations/ABC123",
"created_at": "2026-03-24T10:00:00Z",
"email": "jane@exemple.com",
"event": "https://api.calendly.com/scheduled_events/ABC123",
"name": "Jeanne 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
}
]
}
Webhooks pour les mises à jour en temps réel
Les webhooks notifient votre application des événements de réservation en temps réel.
Créer un abonnement webhook
curl -X POST "https://api.calendly.com/webhook_subscriptions" \
-H "Authorization: Bearer JETON_D_ACCES" \
-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"
}'
Événements disponibles :
invitee.created- Nouvelle réservation effectuéeinvitee.canceled- Réservation annuléeinvitee.rescheduled- Réservation reprogrammée
Lister les abonnements webhook
curl -X GET "https://api.calendly.com/webhook_subscriptions?organization=https://api.calendly.com/organizations/ORG123" \
-H "Authorization: Bearer JETON_D_ACCES"
Supprimer un webhook
curl -X DELETE "https://api.calendly.com/webhook_subscriptions/ID_WEBHOOK" \
-H "Authorization: Bearer JETON_D_ACCES"
Gestion des charges utiles de webhook
Vérifier les signatures de webhook
Calendly signe les webhooks avec une signature dans l'en-tête 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('Signature invalide')
}
// Traiter le webhook
handleWebhook(req.body)
res.status(200).send('OK')
})
Traiter les événements de réservation
function handleWebhook(payload) {
const { event, payload: data } = payload
switch (event) {
case 'invitee.created':
console.log(`Nouvelle réservation : ${data.event.start_time}`)
console.log(`Invité : ${data.email}`)
// Ajouter au CRM, envoyer un e-mail de confirmation, etc.
syncToCRM(data)
break
case 'invitee.canceled':
console.log(`Réservation annulée : ${data.event.uri}`)
// Mettre à jour le CRM, notifier l'équipe, etc.
removeFromCRM(data)
break
case 'invitee.rescheduled':
console.log(`Réservation reprogrammée : ${data.event.start_time}`)
// Mettre à jour le calendrier, notifier l'équipe, etc.
updateCRM(data)
break
}
}
Tester avec Apidog
L'API de Calendly nécessite OAuth, ce qui complique les tests. Apidog simplifie cela.

1. Simuler les réponses OAuth
Pendant le développement, ne passez pas par le flux OAuth complet à chaque fois. Simulez la réponse du jeton :
{
"access_token": "jeton_d_acces_simule",
"refresh_token": "jeton_d_actualisation_simule",
"expires_in": 7200,
"created_at": 1700000000
}
2. Tester les gestionnaires de webhook
Créez des charges utiles de webhook simulées :
{
"created_at": "2026-03-24T10:00:00Z",
"event": "invitee.created",
"payload": {
"email": "test@exemple.com",
"name": "Utilisateur de test",
"event": {
"start_time": "2026-03-25T10:30:00Z",
"end_time": "2026-03-25T11:00:00Z",
"event_type": {
"name": "Consultation de 30 min"
}
}
}
}
Envoyez-les à votre point d'extrémité webhook et vérifiez leur traitement.
3. Variables d'environnement
CALENDLY_CLIENT_ID: abc123
CALENDLY_CLIENT_SECRET: xyz789
CALENDLY_ACCESS_TOKEN: jeton_enregistre
CALENDLY_REFRESH_TOKEN: actualisation_enregistree
CALENDLY_WEBHOOK_SECRET: secret_signature_webhook
4. Valider les signatures de webhook
pm.test('La signature du webhook est valide', () => {
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')
// Vérifier la signature
const valid = verifySignature(payload, signature, secret)
pm.expect(valid).to.be.true
})
Testez les webhooks Calendly avec Apidog - gratuit
Erreurs courantes et correctifs
401 Non autorisé
Cause : Jeton invalide ou expiré.
Correctif :
- Vérifiez que le jeton n'a pas expiré (expiration de 2 heures)
- Utilisez le jeton d'actualisation pour obtenir un nouveau jeton d'accès
- Assurez-vous que l'en-tête Authorization est
Bearer {token}
403 Interdit
Cause : Portée OAuth insuffisante.
Correctif : Le jeton OAuth a besoin des portées appropriées. Lors de la demande d'autorisation, incluez les portées nécessaires. Les portées de Calendly sont implicites en fonction de ce que l'utilisateur autorise.
404 Introuvable
Cause : La ressource n'existe pas ou l'utilisateur n'y a pas accès.
Correctif :
- Vérifiez que l'URI de la ressource est correcte
- Assurez-vous que l'utilisateur authentifié a accès à la ressource
- Vérifiez que le type d'événement ou l'ID d'événement est valide
422 Entité non traitable
Cause : Erreur de validation dans la requête.
Correctif : Vérifiez la réponse pour les détails :
{
"title": "Erreur de validation",
"message": "Paramètre invalide : l'URL doit être une URL HTTPS valide"
}
Alternatives et comparaisons
| Fonctionnalité | Calendly | Acuity | Cal.com | Calendly |
|---|---|---|---|---|
| Tier gratuit | Limité | Limité | Auto-hébergé gratuit | ✓ |
| Accès API | ✓ | ✓ | ✓ | ✓ |
| Webhooks | ✓ | ✓ | ✓ | ✓ |
| OAuth | ✓ | Clé API | Clé API | OAuth |
| Planification d'équipe | ✓ | ✓ | ✓ | ✓ |
| Open source | Non | Non | Oui | Non |
Calendly possède la documentation API et le flux OAuth les plus raffinés. Cal.com est l'alternative open-source avec une authentification par clé API plus simple.
Cas d'utilisation réels
Intégration CRM de vente. Une entreprise SaaS B2B intègre Calendly sur sa page de tarifs. Lorsqu'une personne réserve une démo, le webhook déclenche :
- Création d'un prospect dans Salesforce
- Envoi d'une notification Slack à l'équipe de vente
- Ajout à la séquence d'automatisation marketing
- Enregistrement de l'activité dans la plateforme de succès client
Plateforme de consultation. Une plateforme de services juridiques permet aux clients de réserver des consultations avec des avocats. L'intégration API :
- Synchronise les réservations avec le système de planification interne
- Génère des liens de réunion Zoom
- Envoie un questionnaire d'admission 24 heures avant
- Crée un dossier client une fois la réunion terminée
Planification d'entretiens. Une plateforme de recrutement utilise Calendly pour les entretiens avec les candidats. Les webhooks :
- Mettent à jour l'ATS avec les détails de l'entretien
- Notifient le responsable du recrutement par e-mail
- Envoient des invitations de calendrier à tous les participants
- Suivent les non-présentations pour le suivi
Conclusion
Voici ce que vous avez appris :
- Calendly utilise OAuth 2.0 pour l'authentification API
- Accédez aux types d'événements et aux événements planifiés via l'API
- Les webhooks fournissent des notifications de réservation en temps réel
- Vérifiez toujours les signatures de webhook pour la sécurité
- Testez avec Apidog avant de vous connecter à de vrais calendriers
Vos prochaines étapes :
- Créez une application OAuth dans Calendly
- Implémentez le flux OAuth
- Configurez un abonnement webhook
- Testez avec des charges utiles simulées dans Apidog
- Déployez en production
Testez les webhooks Calendly avec Apidog - gratuit
FAQ
Ai-je besoin d'un forfait Calendly payant pour utiliser l'API ?Non. L'API est disponible sur tous les forfaits, y compris le gratuit. Cependant, les forfaits gratuits ont des fonctionnalités limitées. Les webhooks sont disponibles sur tous les forfaits.
Quelle est la différence entre les webhooks au niveau de l'utilisateur et au niveau de l'organisation ?Les webhooks au niveau de l'utilisateur ne capturent les événements que pour un seul utilisateur. Les webhooks au niveau de l'organisation capturent les événements pour tous les membres de l'équipe. La plupart des intégrations utilisent la portée de l'organisation.
Comment obtenir le secret de signature du webhook ?Lorsque vous créez un webhook via l'API, la réponse inclut une signing_key. Stockez-la en toute sécurité. Elle est utilisée pour vérifier les signatures de webhook.
Puis-je créer des réservations via l'API ?Non. Calendly ne dispose pas de point d'extrémité API pour créer des réservations. Les réservations doivent être effectuées via l'interface utilisateur de Calendly ou des widgets intégrés. L'API est en lecture seule pour les réservations.
Comment gérer les conversions de fuseaux horaires ?Tous les horodatages dans l'API sont en UTC (ISO 8601). Convertissez-les en heure locale dans votre application. Le fuseau horaire de l'utilisateur est disponible dans la ressource utilisateur.
Quelle est la limite de débit ?Calendly ne documente pas publiquement les limites de débit. Utilisez des modèles de requête raisonnables. Si vous atteignez les limites, implémentez un backoff exponentiel.
Puis-je obtenir des réservations historiques ?Oui. Utilisez min_start_time et max_start_time pour interroger les événements historiques. Il n'y a pas de limite sur la durée de la période que vous pouvez interroger.
Comment tester le flux OAuth localement ?Utilisez un service de tunneling comme ngrok pour exposer votre serveur local. Définissez l'URI de redirection sur votre URL ngrok. Complétez le flux OAuth dans un navigateur, puis inspectez le rappel.
