Calendly コネクタ

Tajo を介して Calendly を Brevo に接続し、ミーティング招待者を連絡先として自動的に同期し、予約イベントに基づいてメールシーケンスをトリガーし、営業およびオンボーディングワークフローを効率化します。

概要

プロパティ
プラットフォームCalendly
カテゴリスケジューリング(カスタム)
セットアップの複雑さ簡単
公式統合いいえ
同期データイベント、連絡先、予約、キャンセル
認証方式OAuth 2.0 / Personal Access Token

機能

  • 招待者の同期 - ミーティング招待者から Brevo 連絡先を自動作成
  • 予約トリガー - ミーティングが予約されたときに Brevo 自動化を起動
  • キャンセル処理 - キャンセル時に再エンゲージメントフローをトリガー
  • ノーショー検出 - 招待者がミーティングに参加しなかった場合に連絡先ステータスを更新
  • イベントタイプマッピング - 異なる Calendly イベントタイプを Brevo リストにマッピング
  • スケジューリング API - リダイレクトなしでアプリに直接スケジューリングを構築

前提条件

開始する前に、以下を準備してください。

  1. Calendly アカウント(API アクセスには Professional プラン以上が必要)
  2. Calendly Integrations からの Personal Access Token
  3. API アクセス可能な Brevo アカウント
  4. コネクタ権限を持つ Tajo アカウント

認証

Personal Access Token

Terminal window
# https://calendly.com/integrations/api_webhooks で生成
export CALENDLY_ACCESS_TOKEN=your_personal_access_token
export TAJO_API_KEY=your_tajo_api_key
export BREVO_API_KEY=your_brevo_api_key

OAuth 2.0

// OAuth 2.0 認可コードフロー
const authUrl = 'https://auth.calendly.com/oauth/authorize?' +
new URLSearchParams({
client_id: process.env.CALENDLY_CLIENT_ID,
redirect_uri: 'https://your-app.com/callback',
response_type: 'code'
});
// コードをトークンと交換
const tokenResponse = await fetch('https://auth.calendly.com/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code: authorizationCode,
client_id: process.env.CALENDLY_CLIENT_ID,
client_secret: process.env.CALENDLY_CLIENT_SECRET,
redirect_uri: 'https://your-app.com/callback'
})
});

設定

基本セットアップ

connectors:
calendly:
enabled: true
access_token: "${CALENDLY_ACCESS_TOKEN}"
sync:
contacts: true
events: true
cancellations: true
event_mapping:
discovery_call:
list_id: 10
event_type_uri: "https://api.calendly.com/event_types/abc123"
demo:
list_id: 11
event_type_uri: "https://api.calendly.com/event_types/xyz789"
webhook:
signing_key: "${CALENDLY_WEBHOOK_SIGNING_KEY}"

フィールドマッピング

field_mapping:
email: email
name: FIRSTNAME
questions_and_answers:
company: COMPANY
role: JOB_TITLE
phone: SMS
event_type_name: CALENDLY_EVENT_TYPE
scheduled_at: MEETING_DATE
status: BOOKING_STATUS

API エンドポイント

エンドポイントメソッド説明
https://api.calendly.com/users/meGET現在のユーザーを取得
https://api.calendly.com/event_typesGETイベントタイプを一覧取得
https://api.calendly.com/scheduled_eventsGETスケジュール済みイベントを一覧取得
https://api.calendly.com/scheduled_events/{uuid}GETスケジュール済みイベントを取得
https://api.calendly.com/scheduled_events/{uuid}/inviteesGET招待者を一覧取得
https://api.calendly.com/scheduling_linksPOSTスケジューリングリンクを作成
https://api.calendly.com/webhook_subscriptionsPOSTWebhook を作成
https://api.calendly.com/webhook_subscriptionsGETWebhook を一覧取得
https://api.calendly.com/invitee_no_shows/{uuid}GETノーショーステータスを取得

コード例

コネクタの初期化

import { TajoClient } from '@tajo/sdk';
const tajo = new TajoClient({
apiKey: process.env.TAJO_API_KEY,
brevoApiKey: process.env.BREVO_API_KEY
});
await tajo.connectors.connect('calendly', {
accessToken: process.env.CALENDLY_ACCESS_TOKEN
});

スケジュール済みイベントの一覧取得

// スケジュール済みイベントを取得
const response = await fetch(
'https://api.calendly.com/scheduled_events?' +
new URLSearchParams({
user: 'https://api.calendly.com/users/YOUR_USER_ID',
min_start_time: '2024-01-01T00:00:00Z',
max_start_time: '2024-12-31T23:59:59Z',
status: 'active',
count: 100
}),
{
headers: {
'Authorization': `Bearer ${process.env.CALENDLY_ACCESS_TOKEN}`,
'Content-Type': 'application/json'
}
}
);
const events = await response.json();

招待者を Brevo に同期

// スケジュール済みイベントの招待者を取得して Brevo に同期
const inviteesResponse = await fetch(
`https://api.calendly.com/scheduled_events/${eventUuid}/invitees`,
{
headers: {
'Authorization': `Bearer ${process.env.CALENDLY_ACCESS_TOKEN}`
}
}
);
const { collection } = await inviteesResponse.json();
for (const invitee of collection) {
await tajo.contacts.sync({
email: invitee.email,
attributes: {
FIRSTNAME: invitee.name,
CALENDLY_EVENT_TYPE: invitee.event,
MEETING_DATE: invitee.created_at,
BOOKING_STATUS: invitee.status
},
listIds: [10]
});
}

Webhook サブスクリプションの設定

// Calendly イベントを購読
const webhook = await fetch(
'https://api.calendly.com/webhook_subscriptions',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.CALENDLY_ACCESS_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://api.tajo.io/webhooks/calendly',
events: [
'invitee.created',
'invitee.canceled',
'invitee_no_show.created'
],
organization: 'https://api.calendly.com/organizations/YOUR_ORG_ID',
scope: 'organization',
signing_key: process.env.CALENDLY_WEBHOOK_SIGNING_KEY
})
}
);

Webhook イベントの処理

app.post('/webhooks/calendly', async (req, res) => {
// Webhook 署名を検証
const signature = req.headers['calendly-webhook-signature'];
const isValid = verifyCalendlySignature(
req.rawBody, signature, process.env.CALENDLY_WEBHOOK_SIGNING_KEY
);
if (!isValid) return res.status(401).send('Unauthorized');
const { event, payload } = req.body;
switch (event) {
case 'invitee.created':
await tajo.contacts.sync({
email: payload.email,
attributes: { BOOKING_STATUS: 'booked' },
listIds: [10]
});
break;
case 'invitee.canceled':
await tajo.contacts.update(payload.email, {
attributes: { BOOKING_STATUS: 'cancelled' }
});
break;
case 'invitee_no_show.created':
await tajo.contacts.update(payload.email, {
attributes: { BOOKING_STATUS: 'no_show' }
});
break;
}
res.status(200).send('OK');
});

レート制限

リソース制限備考
API リクエスト6,000/分組織全体の制限
Webhook サブスクリプション組織あたり 30 件すべてのイベントタイプ合計
スケジューリングリンク無制限分単位の制限なし

ページネーション

Calendly API のレスポンスはカーソルベースのページネーションを使用します。追加の結果を取得するには、pagination オブジェクトの next_page_token を使用してください。デフォルトのページサイズは 20 アイテム、最大 100 です。

トラブルシューティング

問題原因解決策
Webhook を受信できない間違ったスコープWebhook には organization スコープを使用
401 Unauthorizedトークンの期限切れ新しいトークンを生成するか OAuth トークンをリフレッシュ
招待者データが欠落質問が未設定イベントタイプにカスタム質問を追加
重複した連絡先重複排除ロジックなしアップサートにメールを一意識別子として使用
レート制限 429リクエスト過多バックオフとリクエストバッチ処理を実装

デバッグモード

connectors:
calendly:
debug: true
log_level: verbose
log_webhooks: true

ベストプラクティス

  1. Webhook を使用する - リアルタイム同期のため invitee.createdinvitee.canceled を購読
  2. カスタム質問を追加する - より豊かな連絡先プロファイルのために会社、役職、電話データを収集
  3. イベントタイプをマッピングする - Calendly イベントタイプごとに異なる Brevo リストを割り当て
  4. ノーショーを処理する - リードスコアリングとフォローアップシーケンスを調整するためにノーショーをトラッキング
  5. スケジューリングリンクを使用する - パーソナライズされた予約体験のために一意のスケジューリングリンクを生成
  6. 組織スコープを設定する - すべてのチームメンバーのイベントをキャプチャするため組織レベルの Webhook を使用

セキュリティ

  • OAuth 2.0 - スコープ付きトークンベース認証
  • Webhook 署名 - 受信 Webhook の HMAC 署名検証
  • HTTPS のみ - すべての API エンドポイントに TLS 暗号化が必要
  • トークンの有効期限 - OAuth トークンは期限切れになり、リフレッシュフローが必要
  • 最小限のスコープ - 必要な OAuth スコープのみリクエスト
  • 安全なストレージ - トークンを環境変数またはシークレットマネージャーに保存

関連リソース

Subscribe to updates

developer-docs

Drop your email or phone number — we'll send you what matters next.

auto-detect
AIアシスタント

こんにちは!ドキュメントについて何でもお聞きください。