DEV Community

Cover image for Cara Menggunakan API Calendly: Panduan Developer untuk Integrasi Penjadwalan
Walse
Walse

Posted on • Originally published at apidog.com

Cara Menggunakan API Calendly: Panduan Developer untuk Integrasi Penjadwalan

Intinya

API Calendly memungkinkan otomatisasi alur kerja penjadwalan. Anda melakukan autentikasi dengan OAuth 2.0, mengakses tipe acara dan pemesanan melalui api.calendly.com, serta menerima pembaruan real-time lewat webhook. Untuk pengujian, gunakan Apidog untuk memvalidasi payload webhook dan menguji integrasi tanpa membuat pemesanan nyata.

Coba Apidog hari ini

Pendahuluan

Calendly memproses jutaan pertemuan tiap bulannya—digunakan untuk panggilan penjualan, sesi dukungan, konsultasi, dan wawancara. API-nya memungkinkan Anda menyematkan penjadwalan ke aplikasi sendiri.

Pola umum: Anda ingin pemesanan Calendly memicu aksi di sistem Anda. Contoh: pengguna memesan demo, CRM Anda diperbarui; konsultasi dijadwalkan, Anda kirim kuesioner; pertemuan dibatalkan, tim Anda mendapat notifikasi.

API Calendly mendukung ini dengan webhook. Setiap ada event (pemesanan dibuat/dibatalkan/dijadwal ulang), Calendly mengirimkan POST ke endpoint Anda. Proses payload tersebut dan tindak lanjuti otomatis.

💡 Jika membangun integrasi penjadwalan, Apidog memudahkan pengujian handler webhook dan validasi payload—tirukan respons Calendly selama development untuk memastikan integrasi Anda menangani semua event sebelum terkoneksi kalender nyata.

Autentikasi dengan OAuth 2.0

Calendly menggunakan OAuth 2.0. Anda tidak bisa memakai API key.

Buat aplikasi OAuth

  1. Buka Calendly → Integrasi → API & Webhook
  2. Klik “Buat Aplikasi Baru”
  3. Atur URI pengalihan (misal: https://yourapp.com/auth/calendly/callback)
  4. Catat client ID dan client secret

Alur OAuth

Langkah 1: Arahkan user ke otorisasi

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

Langkah 2: User otorisasi, diarahkan kembali

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

Langkah 3: Tukar kode ke akses token

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

Langkah 4: Gunakan token

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

Token penyegaran

Token akses kedaluwarsa setelah 2 jam. Untuk mendapatkan token baru gunakan refresh token:

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

Mendapatkan informasi pengguna

Dapatkan user saat ini

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

Contoh respons:

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

Dapatkan keanggotaan organisasi

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

Tipe acara

Tipe acara adalah template meeting yang dibuat user (misal: panggilan 30 menit, konsultasi 60 menit).

Daftar tipe acara

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

Contoh respons:

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

Dapatkan tipe acara tertentu

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

Acara terjadwal (pemesanan)

Acara adalah booking aktual yang dibuat via Calendly.

Daftar acara terjadwal

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

Filter berdasar rentang tanggal:

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

Contoh respons:

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

Dapatkan detail acara

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

Dapatkan peserta suatu acara

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

Respons:

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

Webhook untuk pembaruan real-time

Webhook mengirim notifikasi real-time ke aplikasi Anda tentang event booking.

Buat langganan webhook

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

Event yang tersedia:

  • invitee.created — booking baru dibuat
  • invitee.canceled — booking dibatalkan
  • invitee.rescheduled — booking dijadwal ulang

Daftar langganan webhook

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

Hapus webhook

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

Menangani payload webhook

Verifikasi tanda tangan webhook

Calendly menandatangani webhook melalui header Calendly-Webhook-Signature. Contoh verifikasi (Node.js):

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

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

Proses event booking

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

  switch (event) {
    case 'invitee.created':
      console.log(`New booking: ${data.event.start_time}`)
      console.log(`Invitee: ${data.email}`)
      // Sinkronkan ke CRM, kirim email konfirmasi, dll
      syncToCRM(data)
      break

    case 'invitee.canceled':
      console.log(`Booking canceled: ${data.event.uri}`)
      // Update CRM, notifikasi tim, dll
      removeFromCRM(data)
      break

    case 'invitee.rescheduled':
      console.log(`Booking rescheduled: ${data.event.start_time}`)
      // Update kalender, notifikasi tim, dll
      updateCRM(data)
      break
  }
}
Enter fullscreen mode Exit fullscreen mode

Pengujian dengan Apidog

API Calendly memerlukan OAuth, yang bisa mempersulit pengujian. Apidog menyederhanakan proses ini.

Apidog

1. Mock respons OAuth

Selama dev, tidak perlu alur OAuth penuh. Tirukan respons token:

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

2. Uji handler webhook

Buat payload webhook tiruan:

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

Kirim ke endpoint webhook Anda dan verifikasi handler berjalan sesuai logika.

3. Variabel lingkungan

Gunakan variabel lingkungan berikut untuk integrasi:

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. Validasi tanda tangan webhook

Contoh skrip Postman/Apidog:

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

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

Uji webhook Calendly dengan Apidog — gratis.

Kesalahan umum dan perbaikan

401 Tidak Sah

Penyebab: Token tidak valid/kedaluwarsa.

Solusi:

  1. Periksa token belum kedaluwarsa (2 jam).
  2. Gunakan refresh token untuk akses token baru.
  3. Header Authorization harus Bearer {token}.

403 Terlarang

Penyebab: Lingkup OAuth kurang.

Solusi: Sertakan scope yang dibutuhkan saat meminta otorisasi. Scope Calendly berdasarkan otorisasi user.

404 Tidak Ditemukan

Penyebab: Resource tidak ada atau user tidak punya akses.

Solusi:

  1. Cek URI resource.
  2. Pastikan user yang diautentikasi punya akses.
  3. Pastikan event type/ID valid.

422 Entitas Tidak Dapat Diproses

Penyebab: Validasi request gagal.

Solusi: Lihat respons untuk detail error:

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

Alternatif dan perbandingan

Fitur Calendly Acuity Cal.com Calendly
Paket gratis Terbatas Terbatas Gratis mandiri
Akses API
Webhook
OAuth Kunci API Kunci API OAuth
Penjadwalan tim
Sumber terbuka Tidak Tidak Ya Tidak

Calendly punya dokumentasi API dan alur OAuth paling rapi. Cal.com adalah alternatif open-source dengan autentikasi API key yang sederhana.

Kasus penggunaan dunia nyata

Integrasi CRM Penjualan:

Perusahaan SaaS B2B menyematkan Calendly di halaman harga. Saat demo dipesan, webhook memicu:

  1. Buat lead di Salesforce
  2. Notifikasi Slack ke tim sales
  3. Tambahkan ke automasi marketing
  4. Catat aktivitas di platform customer success

Platform konsultasi:

Platform layanan hukum memungkinkan klien booking konsultasi dengan pengacara. Integrasi API:

  1. Sinkronkan booking ke sistem internal
  2. Generate link Zoom
  3. Kirim kuesioner 24 jam sebelum meeting
  4. Buat berkas kasus setelah meeting

Penjadwalan wawancara:

Platform rekrutmen menggunakan Calendly untuk interview kandidat. Webhook:

  1. Update ATS dengan detail wawancara
  2. Notifikasi email ke hiring manager
  3. Kirim undangan kalender ke peserta
  4. Lacak absensi untuk follow up

Kesimpulan

Yang telah Anda pelajari:

  • Calendly menggunakan OAuth 2.0 untuk autentikasi API
  • Akses tipe acara dan acara terjadwal lewat API
  • Webhook menyediakan notifikasi pemesanan real time
  • Selalu verifikasi tanda tangan webhook demi keamanan
  • Uji dengan Apidog sebelum koneksi ke kalender nyata

Langkah selanjutnya:

  1. Buat aplikasi OAuth di Calendly
  2. Implementasikan alur OAuth
  3. Siapkan webhook subscription
  4. Uji dengan payload tiruan di Apidog
  5. Deploy ke produksi

Uji webhook Calendly dengan Apidog — gratis.

FAQ

Apakah perlu paket berbayar untuk API Calendly?

Tidak. API tersedia di semua paket, termasuk gratis (fitur terbatas). Webhook tersedia di semua paket.

Perbedaan webhook user dan organisasi?

Webhook user hanya untuk event user itu. Webhook organisasi untuk semua tim. Mayoritas integrasi gunakan scope organisasi.

Bagaimana mendapatkan webhook signing secret?

Saat membuat webhook via API, respons memuat signing_key. Simpan dengan aman, gunakan untuk verifikasi signature.

Bisakah membuat booking via API?

Tidak. Calendly tidak punya endpoint untuk membuat booking. Booking hanya via UI atau widget. API hanya read-only untuk booking.

Cara handle konversi zona waktu?

Semua timestamp API dalam UTC (ISO 8601). Konversi ke waktu lokal di aplikasi Anda. Zona waktu user tersedia di resource user.

Berapa rate limitnya?

Calendly tidak mendokumentasikan rate limit publik. Gunakan permintaan wajar. Jika limit tercapai, terapkan backoff eksponensial.

Bisa dapatkan booking historis?

Ya. Gunakan min_start_time & max_start_time untuk query event historis. Tidak ada batas seberapa jauh ke belakang.

Cara uji OAuth flow secara lokal?

Gunakan tunneling seperti ngrok untuk expose server lokal Anda. Set URI pengalihan ke URL ngrok. Selesaikan alur OAuth di browser lalu cek callback.

Top comments (0)