موصل Calendly

اربط Calendly بـ Brevo عبر Tajo لمزامنة المدعوين إلى الاجتماعات تلقائيًا كجهات اتصال، وتشغيل تسلسلات البريد الإلكتروني بناءً على أحداث الحجز، وتبسيط سير عمل المبيعات والتأهيل.

نظرة عامة

الخاصيةالقيمة
المنصةCalendly
الفئةالجدولة (مخصص)
تعقيد الإعدادسهل
تكامل رسميلا
البيانات المتزامنةالأحداث، جهات الاتصال، الحجوزات، الإلغاءات
طريقة المصادقةOAuth 2.0 / Personal Access Token

الميزات

  • مزامنة المدعوين - أنشئ جهات اتصال Brevo تلقائيًا من المدعوين إلى الاجتماعات
  • مشغلات الحجز - أطلق أتمتة Brevo عند حجز الاجتماعات
  • معالجة الإلغاء - شغّل تدفقات إعادة التفاعل عند الإلغاءات
  • اكتشاف عدم الحضور - حدّث حالة جهة الاتصال عندما يفوّت المدعوون الاجتماعات
  • ربط أنواع الأحداث - اربط أنواع أحداث Calendly المختلفة بقوائم Brevo
  • 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إنشاء webhook
https://api.calendly.com/webhook_subscriptionsGETعرض webhooks
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
});

عرض الأحداث المجدولة

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

إعداد اشتراكات Webhook

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

معالجة أحداث 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');
});

حدود المعدل

الموردالحدملاحظات
طلبات API6,000/دقيقةحد على مستوى المؤسسة
اشتراكات Webhook30 لكل مؤسسةعبر جميع أنواع الأحداث
روابط الجدولةغير محدودلا يوجد حد لكل دقيقة

الترقيم

تستخدم استجابات Calendly API الترقيم القائم على المؤشر. استخدم next_page_token من كائن pagination لاسترجاع النتائج الإضافية. حجم الصفحة الافتراضي هو 20 عنصرًا، بحد أقصى 100.

استكشاف الأخطاء

المشكلةالسببالحل
Webhook لم يُستلمنطاق خاطئاستخدم نطاق organization لـ webhooks
401 Unauthorizedانتهت صلاحية الرمزولّد رمزًا جديدًا أو جدد رمز OAuth
بيانات المدعو مفقودةالأسئلة غير مُعدةأضف أسئلة مخصصة إلى نوع الحدث
جهات اتصال مكررةلا يوجد منطق إزالة تكراراستخدم البريد الإلكتروني كمعرف فريد للـ upserts
حد معدل 429عدد كبير من الطلباتنفّذ التراجع وتجميع الطلبات

وضع التصحيح

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

أفضل الممارسات

  1. استخدم webhooks - اشترك في invitee.created و invitee.canceled للمزامنة في الوقت الفعلي
  2. أضف أسئلة مخصصة - اجمع بيانات الشركة والدور والهاتف لملفات جهات اتصال أغنى
  3. اربط أنواع الأحداث - عيّن قوائم Brevo مختلفة لكل نوع حدث Calendly
  4. تعامل مع عدم الحضور - تتبع حالات عدم الحضور لضبط تسجيل العملاء المحتملين وتسلسلات المتابعة
  5. استخدم روابط الجدولة - ولّد روابط جدولة فريدة لتجارب حجز مخصصة
  6. اضبط نطاق المؤسسة - استخدم webhooks على مستوى المؤسسة لالتقاط الأحداث من جميع أعضاء الفريق

الأمان

  • OAuth 2.0 - مصادقة قائمة على الرمز محددة النطاق
  • توقيعات Webhook - التحقق من توقيع HMAC للـ webhooks الواردة
  • 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

مرحباً! اسألني أي شيء عن الوثائق.