DEV Community

Cover image for Calendly API Kullanımı: Geliştirici Takvim Entegrasyon Rehberi
Tobias Hoffmann
Tobias Hoffmann

Posted on • Originally published at apidog.com

Calendly API Kullanımı: Geliştirici Takvim Entegrasyon Rehberi

Kısaca

Calendly API'leri ile planlama iş akışlarını otomatikleştirmek için OAuth 2.0 ile kimlik doğrulaması yapabilir, api.calendly.com üzerinden etkinlik türleri ve rezervasyonlara erişebilir, webhook'lar ile gerçek zamanlı bildirimler alabilirsiniz. Gerçek rezervasyon oluşturmadan entegrasyonunuzu ve webhook yüklerini doğrulamak için Apidog'u kullanarak test sürecinizi hızlandırabilirsiniz.

Apidog'u bugün deneyin

Giriş

Calendly, her ay milyonlarca toplantı yönetir ve yaygın olarak satış, destek, danışmanlık ve mülakatlar için kullanılır. Calendly API, planlama işlemlerini doğrudan kendi uygulamanıza entegre etmenizi sağlar.

Örnek Senaryo: Kullanıcı bir demo rezervasyonu yaptığında CRM'iniz otomatik güncellensin, danışmanlık planlandığında anket gönderilsin veya toplantı iptal edildiğinde ekibiniz bilgilendirilsin. Bunları, Calendly'nin webhook altyapısı ile kolayca tetikleyebilirsiniz: Rezervasyon oluşturulduğunda, iptal edildiğinde veya yeniden planlandığında Calendly, webhook uç noktanıza POST isteği gönderir; bu yükü işleyerek otomatik aksiyonlar başlatabilirsiniz.

💡 İpucu: Planlama entegrasyonları geliştiriyorsanız, Apidog ile webhook işleyicilerini ve yüklerini test edebilirsiniz. Geliştirme aşamasında Calendly yanıtlarını taklit ederek entegrasyonunuzun tüm etkinlikleri doğru işlediğinden emin olun.

OAuth 2.0 ile Kimlik Doğrulama

Calendly API erişimi için yalnızca OAuth 2.0 desteklenir, API anahtarı kullanılamaz.

Bir OAuth uygulaması oluşturun

  1. Calendly → Entegrasyonlar → API ve Webhook'lar bölümüne gidin.
  2. "Yeni Uygulama Oluştur"a tıklayın.
  3. Yönlendirme URI'nızı girin (örn. https://yourapp.com/auth/calendly/callback).
  4. İstemci Kimliğinizi (client ID) ve İstemci Sırrınızı (client secret) alın.

OAuth akışını uygulayın

Adım 1: Kullanıcıyı yetkilendirme ekranına yönlendirin

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

Adım 2: Kullanıcı yetki verir ve geri yönlendirilir

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

Adım 3: Authorization code'u access token ile değiştirin

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

Adım 4: Erişim belirtecini kullanarak API çağrısı yapın

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

Yenileme belirteçleri

Erişim belirteçleri 2 saatte bir sona erer. Otomatik yenilemek için refresh token kullanın:

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

Kullanıcı Bilgileri Alma

Mevcut kullanıcıyı getir

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

Yanıt örneği:

{
  "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

Kuruluş üyeliğini getir

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

Etkinlik Türleri

Etkinlik türleri, kullanıcıların oluşturduğu toplantı şablonlarıdır (ör. 30 dakikalık görüşme).

Etkinlik türlerini listele

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

Yanıt örneği:

{
  "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

Belirli bir etkinlik türünü getir

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

Planlanmış Etkinlikler (Rezervasyonlar)

Etkinlikler, Calendly üzerinden yapılan gerçek rezervasyonlardır.

Planlanmış etkinlikleri listele

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

Tarih aralığına göre filtreleyin:

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

Yanıt örneği:

{
  "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

Etkinlik detaylarını getir

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

Bir etkinlik için davetlileri al

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

Yanıt örneği:

{
  "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

Gerçek Zamanlı Güncellemeler için Webhook'lar

Webhook'lar ile uygulamanıza rezervasyon etkinlikleri anında bildirilir.

Webhook aboneliği oluştur

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

Desteklenen etkinlikler:

  • invitee.created: Yeni rezervasyon yapıldı
  • invitee.canceled: Rezervasyon iptal edildi
  • invitee.rescheduled: Rezervasyon yeniden planlandı

Webhook aboneliklerini listele

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

Bir webhook'u sil

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

Webhook Yüklerini İşleme

Webhook imzalarını doğrula

Calendly, Calendly-Webhook-Signature başlığında bir HMAC imzası gönderir. Gelen payload'ın doğruluğunu aşağıdaki şekilde kontrol edin:

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'u işle
  handleWebhook(req.body)
  res.status(200).send('OK')
})
Enter fullscreen mode Exit fullscreen mode

Rezervasyon etkinliklerini işle

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

  switch (event) {
    case 'invitee.created':
      console.log(`Yeni rezervasyon: ${data.event.start_time}`)
      console.log(`Davetli: ${data.email}`)
      // CRM'e ekle, onay maili gönder vb.
      syncToCRM(data)
      break

    case 'invitee.canceled':
      console.log(`Rezervasyon iptal: ${data.event.uri}`)
      // CRM'den çıkar, ekibe bildir vb.
      removeFromCRM(data)
      break

    case 'invitee.rescheduled':
      console.log(`Rezervasyon yeniden planlandı: ${data.event.start_time}`)
      // Takvimi güncelle, ekibe bildir vb.
      updateCRM(data)
      break
  }
}
Enter fullscreen mode Exit fullscreen mode

Apidog ile Test Etme

Calendly'nin OAuth gerektirmesi test sürecini karmaşıklaştırabilir. Apidog ile aşağıdaki adımları uygulayarak entegrasyonunuzu kolayca test edebilirsiniz.

resim-237

1. OAuth yanıtlarını taklit etme

Geliştirme ortamında gerçek OAuth akışını tekrar tekrar çalıştırmak yerine, aşağıdaki gibi sahte bir access token kullanın:

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

2. Webhook işleyicilerini test etme

Taklit bir webhook yükü oluşturup uç noktanıza gönderin:

{
  "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

Webhook endpoint'inize göndererek test edin.

3. Ortam değişkenleri

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 imzalarını doğrula

Apidog veya benzer bir ortamda otomatik test için:

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

  // İmzayı doğrula
  const valid = verifySignature(payload, signature, secret)
  pm.expect(valid).to.be.true
})
Enter fullscreen mode Exit fullscreen mode

Calendly webhook'larını Apidog ile ücretsiz test edebilirsiniz.

Yaygın Hatalar ve Düzeltmeler

401 Yetkilendirilmedi

  • Neden: Geçersiz veya süresi dolmuş access token.
  • Çözüm:
    1. Token'ın geçerlilik süresini (2 saat) kontrol edin.
    2. Refresh token ile yeni bir access token alın.
    3. Authorization header'ın Bearer {token} formatında olduğuna emin olun.

403 Yasak

  • Neden: OAuth token kapsamı yetersiz.
  • Çözüm: Gerekli kapsamları isteme sırasında ekleyin ve kullanıcının izin verdiğinden emin olun.

404 Bulunamadı

  • Neden: Kaynak yok veya erişim izniniz yok.
  • Çözüm:
    1. URI'nın doğruluğunu kontrol edin.
    2. Kullanıcının kaynağa erişimi olduğundan emin olun.
    3. Etkinlik türü veya etkinlik id'sinin geçerli olup olmadığını kontrol edin.

422 İşlenemeyen Varlık

  • Neden: API isteğinde doğrulama hatası.
  • Çözüm: Yanıttaki hata mesajını inceleyin.
{
  "title": "Validation Error",
  "message": "Invalid parameter: url must be a valid HTTPS URL"
}
Enter fullscreen mode Exit fullscreen mode

Alternatifler ve Karşılaştırmalar

Özellik Calendly Acuity Cal.com Calendly
Ücretsiz katman Sınırlı Sınırlı Kendi kendine barındırılan ücretsiz
API erişimi
Webhook'lar
OAuth API anahtarı API anahtarı OAuth
Ekip planlama
Açık kaynak Hayır Hayır Evet Hayır

Calendly, kapsamlı API dokümantasyonu ve OAuth desteğiyle öne çıkar. Cal.com ise API anahtarıyla kimlik doğrulama sunan açık kaynak bir alternatiftir.

Gerçek Dünya Kullanım Senaryoları

Satış CRM entegrasyonu

Bir B2B SaaS şirketi, Calendly'yi fiyatlandırma sayfasına gömerek, rezervasyon sonrası aşağıdaki aksiyonları otomatikleştirir:

  1. Salesforce'ta potansiyel müşteri oluşturur
  2. Satış ekibine Slack bildirimi gönderir
  3. Pazarlama otomasyonuna ekler
  4. Müşteri başarı platformunda etkinlik kaydeder

Danışmanlık platformu

Bir hukuk platformunda rezervasyonlar API ile:

  1. İç planlama sistemine senkronize edilir
  2. Zoom toplantı linki oluşturulur
  3. 24 saat önce başvuru anketi gönderilir
  4. Toplantı sonrası dava dosyası otomatik oluşturulur

Mülakat planlaması

Bir işe alım platformu, Calendly ve webhook'lar ile:

  1. ATS'yi mülakat bilgileriyle günceller
  2. Yöneticilere e-posta bildirimi gönderir
  3. Katılımcıların takvimlerine davet yollar
  4. Gelmeyenleri takip eder

Sonuç

Bu makalede özetle:

  • Calendly, API kimlik doğrulaması için OAuth 2.0 kullanır
  • Etkinlik türleri ve rezervasyonlara API ile erişebilirsiniz
  • Webhook'lar gerçek zamanlı rezervasyon bildirimleri sağlar
  • Webhook imzalarını güvenlik için mutlaka doğrulayın
  • Gerçek takvimlere bağlanmadan önce Apidog ile test edin

Uygulama adımlarınız:

  1. Calendly'de bir OAuth uygulaması oluşturun
  2. OAuth akışını kodunuza entegre edin
  3. Webhook aboneliği kurun
  4. Apidog'da sahte yüklerle entegrasyonunuzu test edin
  5. Üretime alın

Calendly webhook'larını Apidog ile ücretsiz test edebilirsiniz.

Sıkça Sorulan Sorular

API'yi kullanmak için ücretli bir Calendly planına ihtiyacım var mı?

Hayır, API tüm planlarda mevcut. Ücretsiz planlarda bazı kısıtlamalar olabilir. Webhook'lar tüm planlarda çalışır.

Kullanıcı ve kuruluş düzeyinde webhook farkı nedir?

Kullanıcı düzeyinde webhook yalnızca bir kullanıcıya ait etkinlikleri yakalar. Kuruluş düzeyinde ise tüm ekip üyeleri için geçerlidir. Çoğu entegrasyon için kuruluş kapsamı önerilir.

Webhook imzalama sırrını nasıl alırım?

API ile webhook oluşturduğunuzda, yanıt içinde bir signing_key gelir. Bunu güvenli şekilde saklayın ve webhook doğrulamasında kullanın.

API ile rezervasyon oluşturabilir miyim?

Hayır, Calendly'nin API üzerinden rezervasyon oluşturma uç noktası yoktur. Rezervasyonlar, kullanıcı arayüzü veya widget ile yapılmalıdır. API sadece okuma işlemleri içindir.

Saat dilimi dönüşümü nasıl yapılır?

API tüm zaman damgalarını UTC (ISO 8601) ile döndürür. Kullanıcı kaynağında saat dilimi bilgisi mevcuttur; uygulamanızda yerel saate dönüştürebilirsiniz.

Oran limiti var mı?

Calendly oran limitlerini açıkça belirtmez. Makul istek seviyelerinde kalın ve limit aşımında exponential backoff algoritması kullanın.

Geçmiş rezervasyonlara erişebilir miyim?

Evet. min_start_time ve max_start_time ile istediğiniz tarih aralığını sorgulayabilirsiniz. Geriye dönük sorgulama için bir sınır yoktur.

OAuth akışını yerelde nasıl test ederim?

Ngrok gibi bir tünel aracı ile lokal sunucunuzu internete açın. Yönlendirme URI'sini ngrok URL'sine ayarlayın ve OAuth akışını tarayıcıdan test edin.

Top comments (0)