Коннектор Calendly

Подключите Calendly к Brevo через Tajo, чтобы автоматически синхронизировать приглашённых на встречи как контактов, запускать email-последовательности по событиям бронирования и оптимизировать процессы продаж и онбординга.

Обзор

СвойствоЗначение
ПлатформаCalendly
КатегорияПланирование (Custom)
Сложность настройкиЛёгкая
Официальная интеграцияНет
Синхронизируемые данныеСобытия, контакты, бронирования, отмены
Метод аутентификацииOAuth 2.0 / Personal Access Token

Возможности

  • Синхронизация приглашённых, автоматически создавайте контакты Brevo из приглашённых на встречи
  • Триггеры бронирования, запускайте автоматизации Brevo при бронировании встреч
  • Обработка отмен, запускайте re-engagement-сценарии при отменах
  • Обнаружение no-show, обновляйте статус контакта, когда приглашённые пропускают встречи
  • Сопоставление типов событий, сопоставляйте разные типы событий Calendly со списками Brevo
  • Scheduling API, встраивайте планирование непосредственно в ваше приложение без редиректов

Предварительные требования

Прежде чем начать, убедитесь, что у вас есть:

  1. Аккаунт Calendly (тариф Professional или выше для доступа к API)
  2. Personal Access Token из Calendly Integrations
  3. Аккаунт Brevo с доступом к API
  4. Аккаунт Tajo с правами на коннекторы

Аутентификация

Personal Access Token

Terminal window
# Generate at 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 Authorization Code Flow
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'
});
// Exchange code for token
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_subscriptionsPOSTСоздать вебхук
https://api.calendly.com/webhook_subscriptionsGETСписок вебхуков
https://api.calendly.com/invitee_no_shows/{uuid}GETПолучить статус no-show

Примеры кода

Инициализация коннектора

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

Список запланированных событий

// Retrieve scheduled events
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

// Get invitees for a scheduled event and sync to 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]
});
}

Настройка подписок на вебхуки

// Subscribe to Calendly events
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
})
}
);

Обработка событий вебхуков

app.post('/webhooks/calendly', async (req, res) => {
// Verify webhook signature
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');
});

Ограничения скорости

РесурсЛимитПримечания
Запросы API6 000/минЛимит на всю организацию
Подписки на вебхуки30 на организациюПо всем типам событий
Ссылки планированияБез ограниченийНет лимита в минуту

Пагинация

Ответы Calendly API используют пагинацию на основе курсора. Используйте next_page_token из объекта pagination для получения дополнительных результатов. Размер страницы по умолчанию, 20 элементов, максимум, 100.

Устранение неполадок

ПроблемаПричинаРешение
Вебхук не полученНеверный scopeИспользуйте scope organization для вебхуков
401 UnauthorizedТокен истёкСгенерируйте новый токен или обновите OAuth-токен
Отсутствуют данные приглашённогоВопросы не настроеныДобавьте кастомные вопросы к типу события
Дубликаты контактовНет логики дедупликацииИспользуйте email как уникальный идентификатор для upsert
Лимит 429Слишком много запросовРеализуйте задержку и пакетирование запросов

Режим отладки

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

Лучшие практики

  1. Используйте вебхуки, подпишитесь на invitee.created и invitee.canceled для синхронизации в реальном времени
  2. Добавляйте кастомные вопросы, собирайте данные о компании, роли и телефоне для более богатых профилей контактов
  3. Сопоставляйте типы событий, назначайте разные списки Brevo для каждого типа события Calendly
  4. Обрабатывайте no-show, отслеживайте no-show для корректировки скоринга лидов и последовательностей follow-up
  5. Используйте scheduling links, генерируйте уникальные ссылки планирования для персонализированного опыта бронирования
  6. Устанавливайте scope организации, используйте вебхуки на уровне организации, чтобы захватывать события всех участников команды

Безопасность

  • OAuth 2.0, аутентификация на основе scoped-токенов
  • Подписи вебхуков, проверка HMAC-подписи для входящих вебхуков
  • Только HTTPS, все эндпоинты API требуют TLS-шифрования
  • Истечение токенов, OAuth-токены истекают и требуют refresh flow
  • Минимальные scope, запрашивайте только необходимые OAuth scope
  • Безопасное хранение, храните токены в переменных окружения или менеджерах секретов

Связанные ресурсы

Subscribe to updates

developer-docs

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

auto-detect
AI-ассистент

Привет! Спрашивайте меня о документации.