Конектор Calendly
Свържете Calendly с Brevo чрез Tajo, за да синхронизирате автоматично поканените на срещи като контакти, да задействате имейл последователности на базата на събития за резервация и да оптимизирате работните потоци за продажби и onboarding.
Преглед
| Свойство | Стойност |
|---|---|
| Платформа | Calendly |
| Категория | Scheduling (Персонализирана) |
| Сложност на настройка | Лесна |
| Официална интеграция | Не |
| Синхронизирани данни | Събития, контакти, резервации, отмяни |
| Метод на автентикация | OAuth 2.0 / Personal Access Token |
Функции
- Синхронизация на поканени – Автоматично създавайте контакти в Brevo от поканените на срещи
- Тригери за резервации – Задействайте автоматизации в Brevo, когато се резервират срещи
- Обработка на отмени – Задействайте потоци за повторна ангажираност при отмени
- Откриване на no-show – Обновявайте статуса на контакта, когато поканените пропуснат срещи
- Мапване на типове събития – Мапвайте различни типове събития в Calendly към списъци в Brevo
- Scheduling API – Вградете планирането директно във вашето приложение без пренасочвания
Предварителни условия
Преди да започнете, уверете се, че имате:
- Акаунт в Calendly (Professional план или по-горе за API достъп)
- Personal Access Token от Calendly Integrations
- Акаунт в Brevo с API достъп
- Акаунт в Tajo с разрешения за конектори
Автентикация
Personal Access Token
# Generate at https://calendly.com/integrations/api_webhooksexport CALENDLY_ACCESS_TOKEN=your_personal_access_tokenexport TAJO_API_KEY=your_tajo_api_keyexport BREVO_API_KEY=your_brevo_api_keyOAuth 2.0
// OAuth 2.0 Authorization Code Flowconst 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 tokenconst 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_STATUSAPI крайни точки
| Endpoint | Method | Описание |
|---|---|---|
https://api.calendly.com/users/me | GET | Извличане на текущия потребител |
https://api.calendly.com/event_types | GET | Списък на типовете събития |
https://api.calendly.com/scheduled_events | GET | Списък на планираните събития |
https://api.calendly.com/scheduled_events/{uuid} | GET | Извличане на планирано събитие |
https://api.calendly.com/scheduled_events/{uuid}/invitees | GET | Списък на поканените |
https://api.calendly.com/scheduling_links | POST | Създаване на връзка за планиране |
https://api.calendly.com/webhook_subscriptions | POST | Създаване на webhook |
https://api.calendly.com/webhook_subscriptions | GET | Списък на webhooks |
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 eventsconst 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 Brevoconst 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 абонаменти
// Subscribe to Calendly eventsconst 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) => { // 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');});Лимити на заявки
| Ресурс | Лимит | Забележки |
|---|---|---|
| API заявки | 6000/мин | Лимит за цялата организация |
| Webhook абонаменти | 30 за организация | Между всички типове събития |
| Връзки за планиране | Неограничено | Без лимит на минута |
Пагинация
Отговорите на Calendly API използват пагинация на базата на cursor. Използвайте next_page_token от обекта pagination, за да извлечете допълнителни резултати. Размерът на страницата по подразбиране е 20 елемента, с максимум 100.
Отстраняване на проблеми
| Проблем | Причина | Решение |
|---|---|---|
| Webhook не е получен | Грешен scope | Използвайте organization scope за webhooks |
| 401 Unauthorized | Изтекъл токен | Генерирайте нов токен или обновете OAuth токена |
| Липсващи данни за поканения | Въпросите не са конфигурирани | Добавете персонализирани въпроси към типа събитие |
| Дублирани контакти | Няма логика за дедупликация | Използвайте имейла като уникален идентификатор за upsert |
| Rate limit 429 | Твърде много заявки | Приложете отлагане и групиране на заявките |
Debug режим
connectors: calendly: debug: true log_level: verbose log_webhooks: trueНай-добри практики
- Използвайте webhooks – Абонирайте се за
invitee.createdиinvitee.canceledза синхронизация в реално време - Добавете персонализирани въпроси – Събирайте данни за компания, роля и телефон за по-богати профили на контактите
- Мапвайте типовете събития – Присвоявайте различни списъци в Brevo за всеки тип събитие в Calendly
- Обработвайте no-shows – Проследявайте no-shows за корекция на оценката на лийдовете и последователностите за последващи действия
- Използвайте scheduling links – Генерирайте уникални връзки за планиране за персонализирани изживявания при резервация
- Задайте organization scope – Използвайте webhooks на ниво организация за улавяне на събития от всички членове на екипа
Сигурност
- OAuth 2.0 – Автентикация на базата на обхватни токени
- Webhook подписи – HMAC валидация на подписите за входящи webhooks
- Само HTTPS – Всички API крайни точки изискват TLS криптиране
- Изтичане на токени – OAuth токените изтичат и изискват refresh потоци
- Минимални обхвати – Заявявайте само необходимите OAuth обхвати
- Сигурно съхранение – Съхранявайте токените в environment variables или secret managers