Calendly API の使い方:開発者向けスケジュール連携ガイド

Ashley Innocent

Ashley Innocent

24 3月 2026

Calendly API の使い方:開発者向けスケジュール連携ガイド

Apidog エンタープライズ

オンプレミスデプロイ

SSO & RBAC

SOC 2 準拠

Apidog Enterpriseを見る

要約

Calendly APIを使用すると、スケジューリングワークフローを自動化できます。OAuth 2.0で認証し、api.calendly.com経由でイベントタイプと予約にアクセスし、Webhook経由でリアルタイムの更新を受け取ります。テストには、Apidogを使用してWebhookペイロードを検証し、実際の予約を作成せずにインテグレーションをテストできます。

はじめに

Calendlyは毎月何百万もの会議を処理しています。人々はこれを営業電話、サポートセッション、コンサルテーション、面接などに利用しています。APIを使用すると、そのスケジューリング機能を独自のアプリに組み込むことができます。

一般的なパターンとして、Calendlyの予約がシステム内のアクションをトリガーするようにしたい場合があるでしょう。ユーザーがデモを予約すると、CRMが更新されます。コンサルテーションがスケジュールされると、アンケートが送信されます。会議がキャンセルされると、チームに通知されます。

CalendlyのAPIは、これをWebhook経由で処理します。イベントが発生すると(予約の作成、キャンセル、再スケジュール)、CalendlyはエンドポイントにPOSTします。あなたはペイロードを処理し、アクションを実行します。

💡
スケジューリングインテグレーションを構築している場合、ApidogはWebhookハンドラーのテストとペイロードの検証に役立ちます。開発中にCalendlyのレスポンスをモックし、実際のカレンダーに接続する前にすべてのイベントタイプがインテグレーションで処理されることを確認できます。
button

OAuth 2.0による認証

CalendlyはAPIアクセスにOAuth 2.0を使用します。単にAPIキーを使用することはできません。

OAuthアプリケーションの作成

  1. Calendly → 統合 → APIとWebhookに移動します。
  2. 「新規アプリケーションを作成」をクリックします。
  3. リダイレクトURIを設定します(例: https://yourapp.com/auth/calendly/callback)。
  4. クライアントIDとクライアントシークレットを取得します。

OAuthフロー

ステップ1:ユーザーを承認にリダイレクトする

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

ステップ2:ユーザーが承認し、リダイレクトされる

https://yourapp.com/auth/calendly/callback?code=AUTHORIZATION_CODE

ステップ3:コードをアクセストークンと交換する

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

ステップ4:トークンを使用する

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

リフレッシュトークン

アクセストークンは2時間で期限切れになります。新しいアクセストークンを取得するにはリフレッシュトークンを使用します。

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

ユーザー情報の取得

現在のユーザーを取得

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

レスポンス:

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

組織のメンバーシップを取得

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

イベントタイプ

イベントタイプは、ユーザーが作成する会議テンプレートです(30分通話、60分コンサルテーションなど)。

イベントタイプをリスト表示

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

レスポンス:

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

特定のイベントタイプを取得

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

スケジュールされたイベント(予約)

イベントとは、Calendlyを通じて行われた実際の予約のことです。

スケジュールされたイベントをリスト表示

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

日付範囲でフィルター:

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"

レスポンス:

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

イベントの詳細を取得

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

イベントの招待者を取得

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

レスポンス:

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

リアルタイム更新のためのWebhook

Webhookは、予約イベントについてリアルタイムでアプリに通知します。

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

利用可能なイベント:

Webhookサブスクリプションをリスト表示

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

Webhookを削除

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

Webhookペイロードの処理

Webhook署名の検証

Calendlyは、Calendly-Webhook-Signatureヘッダーに署名を含めてWebhookに署名します。

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を処理
  handleWebhook(req.body)
  res.status(200).send('OK')
})

予約イベントの処理

function handleWebhook(payload) {
  const { event, payload: data } = payload
  
  switch (event) {
    case 'invitee.created':
      console.log(`新しい予約: ${data.event.start_time}`)
      console.log(`招待者: ${data.email}`)
      // CRMへの追加、確認メールの送信など
      syncToCRM(data)
      break
      
    case 'invitee.canceled':
      console.log(`予約がキャンセルされました: ${data.event.uri}`)
      // CRMの更新、チームへの通知など
      removeFromCRM(data)
      break
      
    case 'invitee.rescheduled':
      console.log(`予約が再スケジュールされました: ${data.event.start_time}`)
      // カレンダーの更新、チームへの通知など
      updateCRM(data)
      break
  }
}

Apidogを使ったテスト

CalendlyのAPIはOAuthを必要とするため、テストが複雑になります。Apidogはこれを簡素化します。

Apidogのインターフェース例

1. OAuthレスポンスをモックする

開発中は、毎回完全なOAuthフローを実行する必要はありません。トークン応答をモックします。

{
  "access_token": "mock_access_token",
  "refresh_token": "mock_refresh_token",
  "expires_in": 7200,
  "created_at": 1700000000
}

2. Webhookハンドラーをテストする

モックのWebhookペイロードを作成します。

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

これをWebhookエンドポイントに送信し、処理を確認します。

3. 環境変数

CALENDLY_CLIENT_ID: abc123
CALENDLY_CLIENT_SECRET: xyz789
CALENDLY_ACCESS_TOKEN: stored_token
CALENDLY_REFRESH_TOKEN: stored_refresh
CALENDLY_WEBHOOK_SECRET: webhook_signing_secret

4. Webhook署名を検証する

pm.test('Webhook署名が有効', () => {
  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')
  
  // 署名を検証
  const valid = verifySignature(payload, signature, secret)
  pm.expect(valid).to.be.true
})

ApidogでCalendlyのWebhookを無料でテストする

一般的なエラーと修正

401 Unauthorized(認証なし)

原因: 無効なトークンまたは期限切れのトークン。

修正:

  1. トークンが期限切れになっていないか確認する(2時間で期限切れ)。
  2. リフレッシュトークンを使用して新しいアクセストークンを取得する。
  3. AuthorizationヘッダーがBearer {token}であることを確認する。

403 Forbidden(禁止)

原因: OAuthスコープが不足している。

修正: OAuthトークンには適切なスコープが必要です。承認を要求する際に必要なスコープを含めてください。Calendlyのスコープは、ユーザーが承認した内容に基づいて暗黙的に決定されます。

404 Not Found(見つかりません)

原因: リソースが存在しないか、ユーザーにアクセス権がない。

修正:

  1. リソースURIが正しいことを確認する。
  2. 認証されたユーザーがリソースへのアクセス権を持っていることを確認する。
  3. イベントタイプまたはイベントIDが有効であることを確認する。

422 Unprocessable Entity(処理できないエンティティ)

原因: リクエストのバリデーションエラー。

修正: 詳細についてはレスポンスを確認してください。

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

代替手段と比較

機能 Calendly Acuity Cal.com Calendly
無料ティア 制限あり 制限あり セルフホストは無料
APIアクセス
Webhook
OAuth APIキー APIキー OAuth
チームスケジューリング
オープンソース いいえ いいえ はい いいえ

Calendlyは最も洗練されたAPIドキュメントとOAuthフローを持っています。Cal.comは、よりシンプルなAPIキー認証を備えたオープンソースの代替手段です。

実世界のユースケース

営業CRM連携。 B2B SaaS企業が価格設定ページにCalendlyを埋め込んでいます。誰かがデモを予約すると、Webhookが次をトリガーします。

  1. Salesforceでリードを作成する
  2. 営業チームにSlack通知を送信する
  3. マーケティングオートメーションシーケンスに追加する
  4. 顧客成功プラットフォームに活動をログする

コンサルテーションプラットフォーム。 法律サービスプラットフォームが、クライアントが弁護士とのコンサルテーションを予約できるようにしています。API連携により:

  1. 予約を内部スケジューリングシステムと同期する
  2. Zoom会議リンクを生成する
  3. 24時間前に初回アンケートを送信する
  4. 会議完了時にケースファイルを作成する

面接スケジューリング。 採用プラットフォームが、候補者の面接にCalendlyを使用しています。Webhookが次を実行します。

  1. ATSを面接詳細で更新する
  2. 採用担当者にメールで通知する
  3. すべての参加者にカレンダー招待を送信する
  4. フォローアップのために無断欠席者を追跡する

結論

学んだことは以下の通りです。

次のステップ:

  1. CalendlyでOAuthアプリケーションを作成する
  2. OAuthフローを実装する
  3. Webhookサブスクリプションを設定する
  4. Apidogでモックペイロードをテストする
  5. 本番環境にデプロイする

ApidogでCalendlyのWebhookを無料でテストする

よくある質問

APIを使用するために有料のCalendlyプランが必要ですか?
いいえ。APIは無料プランを含むすべてのプランで利用可能です。ただし、無料プランには機能の制限があります。Webhookはすべてのプランで利用できます。

ユーザーレベルと組織レベルのWebhookの違いは何ですか?
ユーザーレベルのWebhookは1人のユーザーのイベントのみをキャプチャします。組織レベルのWebhookはすべてのチームメンバーのイベントをキャプチャします。ほとんどの連携では組織スコープを使用します。

Webhook署名シークレットはどのように入手できますか?
API経由でWebhookを作成すると、レスポンスにsigning_keyが含まれます。これを安全に保管してください。これはWebhook署名を検証するために使用されます。

API経由で予約を作成できますか?
いいえ。Calendlyには予約を作成するAPIエンドポイントはありません。予約はCalendlyのUIまたは埋め込みウィジェットを介して行う必要があります。APIは予約に対して読み取り専用です。

タイムゾーンの変換はどのように処理しますか?
API内のすべてのタイムスタンプはUTC(ISO 8601)です。アプリケーションで現地時間に変換してください。ユーザーのタイムゾーンはユーザーリソースで利用できます。

レート制限はありますか?
Calendlyはレート制限を公に文書化していません。妥当なリクエストパターンを使用してください。制限に達した場合は、指数関数的バックオフを実装してください。

過去の予約を取得できますか?
はい。min_start_timemax_start_timeを使用して過去のイベントをクエリできます。過去にさかのぼってクエリできる期間に制限はありません。

OAuthフローをローカルでテストするにはどうすればよいですか?
ngrokのようなトンネリングサービスを使用して、ローカルサーバーを公開します。リダイレクトURIをngrokのURLに設定します。ブラウザでOAuthフローを完了し、コールバックを検査します。

ApidogでAPIデザイン中心のアプローチを取る

APIの開発と利用をよりシンプルなことにする方法を発見できる