code icon Code

Fetch Calendly Event Details

Fetch full details for a single Calendly event including invitee info and form responses

Source Code

import fs from "fs";
import path from "path";

const [eventUuid, outputPath] = process.argv.slice(2);

if (!eventUuid || !outputPath) {
  console.error("Error: eventUuid and outputPath are required");
  console.error("Usage: node script.js <eventUuid> session/calendly-event.json");
  process.exit(1);
}

console.log(`Fetching Calendly event details for ${eventUuid}...`);

try {
  // Fetch the event details
  const eventRes = await fetch(
    `https://api.calendly.com/scheduled_events/${eventUuid}`,
    { headers: { Authorization: "Bearer PLACEHOLDER_TOKEN" } }
  );
  const eventData = await eventRes.json();

  if (eventData.resource === undefined) {
    throw new Error(`Failed to fetch event: ${JSON.stringify(eventData)}`);
  }

  const event = eventData.resource;
  console.log(`  Event: ${event.name}`);

  // Fetch invitees for this event
  const inviteesRes = await fetch(
    `https://api.calendly.com/scheduled_events/${eventUuid}/invitees?count=100`,
    { headers: { Authorization: "Bearer PLACEHOLDER_TOKEN" } }
  );
  const inviteesData = await inviteesRes.json();

  if (inviteesData.collection === undefined) {
    throw new Error(`Failed to fetch invitees: ${JSON.stringify(inviteesData)}`);
  }

  const invitees = inviteesData.collection;
  console.log(`  Invitees: ${invitees.length}`);

  // Process invitees
  const processedInvitees = invitees.map((invitee) => {
    // Extract questions and answers
    const questionsAndAnswers = (invitee.questions_and_answers || []).map((qa) => ({
      question: qa.question,
      answer: qa.answer,
    }));

    return {
      uri: invitee.uri,
      email: invitee.email,
      name: invitee.name,
      status: invitee.status,
      timezone: invitee.timezone,
      questionsAndAnswers,
      rescheduled: invitee.rescheduled || false,
      rescheduleUrl: invitee.reschedule_url || null,
      cancelUrl: invitee.cancel_url || null,
      createdAt: invitee.created_at,
      updatedAt: invitee.updated_at,
      cancellation: invitee.cancellation || null,
    };
  });

  // Calculate event duration
  const startTime = new Date(event.start_time);
  const endTime = new Date(event.end_time);
  const durationMinutes = Math.round((endTime - startTime) / (1000 * 60));

  // Build location info
  let locationInfo = null;
  if (event.location) {
    locationInfo = {
      type: event.location.type,
      location: event.location.location || null,
      joinUrl: event.location.join_url || null,
      status: event.location.status || null,
      additionalInfo: event.location.additional_info || null,
    };
  }

  // Build output
  const output = {
    uuid: eventUuid,
    uri: event.uri,
    name: event.name,
    status: event.status,
    startTime: event.start_time,
    endTime: event.end_time,
    durationMinutes,
    eventType: event.event_type,
    location: locationInfo,
    createdAt: event.created_at,
    updatedAt: event.updated_at,
    cancellation: event.cancellation || null,
    invitees: processedInvitees,
    summary: {
      inviteeCount: processedInvitees.length,
      hasFormResponses: processedInvitees.some((i) => i.questionsAndAnswers.length > 0),
      canceledCount: processedInvitees.filter((i) => i.status === "canceled").length,
    },
  };

  // Write output
  const dir = path.dirname(outputPath);
  if (dir && dir !== ".") fs.mkdirSync(dir, { recursive: true });
  fs.writeFileSync(outputPath, JSON.stringify(output, null, 2));

  console.log(`\n✓ Event details fetched`);
  console.log(`  Name: ${event.name}`);
  console.log(`  Time: ${event.start_time}`);
  console.log(`  Duration: ${durationMinutes} minutes`);
  console.log(`  Invitees: ${processedInvitees.length}`);

  if (processedInvitees.length > 0) {
    console.log(`\n  Invitees:`);
    processedInvitees.forEach((inv) => {
      console.log(`    - ${inv.name} (${inv.email})`);
      if (inv.questionsAndAnswers.length > 0) {
        console.log(`      Form responses: ${inv.questionsAndAnswers.length}`);
      }
    });
  }

  console.log(`\n  Output: ${outputPath}`);

  console.log(
    JSON.stringify({
      success: true,
      outputPath,
      eventName: event.name,
      inviteeCount: processedInvitees.length,
    })
  );
} catch (error) {
  console.error("Failed:", error.message);
  throw error;
}