> ## Documentation Index
> Fetch the complete documentation index at: https://developer.meetergo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# White-Label Platform Integration

> Embed meetergo scheduling for your platform users

Build scheduling capabilities into your platform so your users can offer appointment booking to their clients. Perfect for marketplaces, directories, and SaaS platforms.

<Info>
  This recipe requires the **API Platform plan** and a Platform API Key. [Book a demo](https://cal.meetergo.com/team/sales/democall) to get access.
</Info>

## Use Cases

* **Professional directories** (e.g., anwalt.de, doctors, consultants) - Let listed professionals accept bookings
* **Marketplaces** - Enable service providers to manage appointments
* **SaaS platforms** - Add scheduling as a feature for your customers
* **Agency tools** - Manage booking for multiple client accounts

## Architecture Overview

```mermaid theme={null}
flowchart TB
    subgraph "Your Platform"
        A[Platform Admin]
        B[Platform User Dashboard]
        C[Public Profile Pages]
    end

    subgraph "meetergo API"
        D[User Management]
        E[Meeting Types]
        F[Booking Availability]
        G[Bookings]
    end

    subgraph "End Users"
        H[Visitors booking appointments]
    end

    A -->|Create platform users| D
    B -->|Manage availability| E
    C -->|Show booking widget| F
    H -->|Book appointments| G
```

## Implementation Steps

### 1. Platform Setup

First, get your API credentials and set up the admin user:

```javascript theme={null}
const MEETERGO_API_KEY = process.env.MEETERGO_API_KEY;
const headers = {
  'Authorization': `Bearer ${MEETERGO_API_KEY}`,
  'Content-Type': 'application/json'
};
```

### 2. Create Users for Your Platform Members

When a user signs up on your platform, create a corresponding meetergo user:

```javascript theme={null}
async function createPlatformUser(platformUser) {
  const response = await fetch('https://api.meetergo.com/v4/user', {
    method: 'POST',
    headers,
    body: JSON.stringify({
      email: platformUser.email,
      givenName: platformUser.firstName,
      familyName: platformUser.lastName,
      timezone: platformUser.timezone || 'Europe/Berlin',
      // Custom availability for professionals
      availability: {
        name: 'Business Hours',
        timezone: platformUser.timezone || 'Europe/Berlin',
        schedule: [
          { dayOfWeek: 'monday', intervals: [{ from: '09:00', to: '18:00' }] },
          { dayOfWeek: 'tuesday', intervals: [{ from: '09:00', to: '18:00' }] },
          { dayOfWeek: 'wednesday', intervals: [{ from: '09:00', to: '18:00' }] },
          { dayOfWeek: 'thursday', intervals: [{ from: '09:00', to: '18:00' }] },
          { dayOfWeek: 'friday', intervals: [{ from: '09:00', to: '17:00' }] }
        ]
      },
      // Default meeting type
      meetingType: {
        name: 'Consultation',
        duration: 30,
        slug: `${platformUser.slug}-consultation`
      }
    })
  });

  const data = await response.json();

  // Store the mapping in your database
  await db.users.update({
    where: { id: platformUser.id },
    data: {
      meetergoUserId: data.userId,
      meetergoMeetingTypeId: data.meetingTypeId,
      bookingUrl: data.bookingUrl
    }
  });

  return data;
}
```

### 3. Embed Booking on Profile Pages

**Option A: Embed the booking widget**

```html theme={null}
<!-- On the professional's public profile page -->
<iframe
  src="https://cal.meetergo.com/embed/{companySlug}/{userSlug}/{meetingTypeSlug}"
  width="100%"
  height="700"
  frameborder="0"
></iframe>
```

**Option B: Build custom UI with API**

```javascript theme={null}
// Fetch available slots
async function getAvailableSlots(meetingTypeId, startDate, endDate) {
  const params = new URLSearchParams({
    meetingTypeId,
    start: startDate,
    end: endDate
  });

  const response = await fetch(
    `https://api.meetergo.com/v4/booking-availability?${params}`,
    { headers }
  );

  return response.json();
}

// Display in your UI
const slots = await getAvailableSlots(meetingTypeId, '2024-01-15', '2024-01-22');

// Render custom calendar component
slots.availableSlots.forEach(slot => {
  // Your custom rendering logic
});
```

### 4. Handle Bookings

```javascript theme={null}
async function createBooking(meetingTypeId, slot, clientInfo) {
  const response = await fetch('https://api.meetergo.com/v4/booking', {
    method: 'POST',
    headers,
    body: JSON.stringify({
      meetingTypeId,
      start: slot.start,
      attendee: {
        email: clientInfo.email,
        fullname: clientInfo.name,
        phone: clientInfo.phone
      }
    })
  });

  const booking = await response.json();

  // Track in your platform's analytics
  await trackBooking(booking);

  return booking;
}
```

## Multi-Tenant Management

### List All Platform Users

```javascript theme={null}
async function getPlatformUsers() {
  const response = await fetch('https://api.meetergo.com/v4/user', {
    headers
  });

  return response.json();
}
```

### Update User Settings

```javascript theme={null}
async function updateUserMeetingType(userId, meetingTypeId, updates) {
  const response = await fetch(
    `https://api.meetergo.com/v4/meeting-type/${meetingTypeId}`,
    {
      method: 'PATCH',
      headers: {
        ...headers,
        'x-meetergo-api-user-id': userId
      },
      body: JSON.stringify(updates)
    }
  );

  return response.json();
}

// Example: Update duration and buffer time
await updateUserMeetingType(userId, meetingTypeId, {
  duration: 45,
  bufferTimeBefore: 15,
  bufferTimeAfter: 10
});
```

### Bulk Operations

```javascript theme={null}
// Create multiple users at once
async function onboardPlatformUsers(users) {
  const results = await Promise.allSettled(
    users.map(user => createPlatformUser(user))
  );

  const successful = results.filter(r => r.status === 'fulfilled');
  const failed = results.filter(r => r.status === 'rejected');

  console.log(`Created ${successful.length} users, ${failed.length} failed`);

  return { successful, failed };
}
```

## Webhook Integration

Get notified of all bookings across your platform:

```javascript theme={null}
// Register a webhook for all booking events
const webhook = await fetch('https://api.meetergo.com/webhooks', {
  method: 'POST',
  headers,
  body: JSON.stringify({
    endpoint: 'https://your-platform.com/webhooks/meetergo',
    description: 'Platform booking notifications',
    eventTypes: ['booking_created', 'booking_cancelled', 'booking_rescheduled']
  })
});
```

Handle webhooks to update your platform:

```javascript theme={null}
app.post('/webhooks/meetergo', async (req, res) => {
  res.status(200).send('OK');

  const { event, data } = req.body;
  const hostUserId = data.hosts[0]?.id;

  // Find the platform user
  const platformUser = await db.users.findFirst({
    where: { meetergoUserId: hostUserId }
  });

  switch (event) {
    case 'booking_created':
      // Update platform analytics
      await db.bookings.create({
        data: {
          platformUserId: platformUser.id,
          clientEmail: data.attendees[0].email,
          scheduledAt: data.start,
          meetergoBookingId: data.id
        }
      });

      // Send platform-specific notification
      await sendPlatformNotification(platformUser, 'new_booking', data);
      break;

    case 'booking_cancelled':
      await db.bookings.update({
        where: { meetergoBookingId: data.id },
        data: { status: 'cancelled' }
      });
      break;
  }
});
```

## Customization Options

### Custom Branding per User

```javascript theme={null}
// Update personal page branding
await fetch(`https://api.meetergo.com/v4/personal-page`, {
  method: 'PATCH',
  headers: {
    ...headers,
    'x-meetergo-api-user-id': userId
  },
  body: JSON.stringify({
    headerTitle: 'Book a consultation',
    headerSubtitle: 'Select a time that works for you',
    primaryColor: '#0066cc'
  })
});
```

### Meeting Type Templates

Create templates that all platform users can use:

```javascript theme={null}
// Create a template
const template = await fetch('https://api.meetergo.com/v4/meeting-type-template/create', {
  method: 'POST',
  headers,
  body: JSON.stringify({
    name: 'Initial Consultation',
    duration: 30,
    description: 'Free initial consultation to discuss your needs'
  })
});

// Assign template to a user (creates a meeting type from template)
await fetch(`https://api.meetergo.com/v4/meeting-type-template/assign/${templateId}`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    userId: platformUserId
  })
});
```

## Best Practices

<Check>
  **Store user mappings** - Keep meetergo user IDs in your database for easy lookup
</Check>

<Check>
  **Use webhooks** - Don't poll for booking changes, use webhooks instead
</Check>

<Check>
  **Handle errors gracefully** - API calls can fail; implement retry logic
</Check>

<Check>
  **Respect rate limits** - Batch operations where possible
</Check>

<Check>
  **Secure your webhook endpoint** - Validate incoming webhook requests
</Check>

<Warning>
  **API key security** - Never expose your API key in client-side code. All API calls should go through your backend.
</Warning>

## Example: Professional Directory

Complete example for a lawyer directory:

```javascript theme={null}
// lawyer-directory.js

class LawyerDirectory {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.headers = {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    };
  }

  // When a lawyer joins the directory
  async onboardLawyer(lawyer) {
    // Create meetergo user
    const meetergoUser = await this.createMeetergoUser({
      email: lawyer.email,
      firstName: lawyer.firstName,
      lastName: lawyer.lastName,
      specialty: lawyer.specialty
    });

    // Create specialized meeting types
    await this.createMeetingTypes(meetergoUser.userId, lawyer.specialty);

    return meetergoUser;
  }

  async createMeetergoUser(lawyer) {
    const response = await fetch('https://api.meetergo.com/v4/user', {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify({
        email: lawyer.email,
        givenName: lawyer.firstName,
        familyName: lawyer.lastName,
        timezone: 'Europe/Berlin',
        meetingType: {
          name: 'Erstberatung',
          duration: 30,
          slug: `${lawyer.firstName.toLowerCase()}-${lawyer.lastName.toLowerCase()}-erstberatung`
        }
      })
    });

    return response.json();
  }

  async createMeetingTypes(userId, specialty) {
    const meetingTypes = [
      { name: 'Telefonische Beratung', duration: 15 },
      { name: 'Ausführliche Beratung', duration: 60 },
      { name: 'Mandatsgespräch', duration: 45 }
    ];

    for (const mt of meetingTypes) {
      await fetch('https://api.meetergo.com/v4/meeting-type', {
        method: 'POST',
        headers: {
          ...this.headers,
          'x-meetergo-api-user-id': userId
        },
        body: JSON.stringify(mt)
      });
    }
  }

  // Render booking widget on lawyer profile
  getEmbedCode(lawyer) {
    return `
      <iframe
        src="${lawyer.bookingUrl}?embed=true"
        width="100%"
        height="700"
        frameborder="0"
        title="Termin buchen bei ${lawyer.firstName} ${lawyer.lastName}"
      ></iframe>
    `;
  }
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Embed Booking Widget" icon="window" href="/developer-docs/recipes/embed-booking-widget">
    Learn more about embedding options
  </Card>

  <Card title="Custom Booking Flow" icon="code" href="/developer-docs/recipes/build-custom-booking-flow">
    Build a fully custom booking experience
  </Card>

  <Card title="Webhooks" icon="webhook" href="/developer-docs/webhooks/overview">
    Set up real-time notifications
  </Card>

  <Card title="Meeting Types" icon="calendar" href="/developer-docs/core-concepts/meeting-types">
    Configure meeting types for your users
  </Card>
</CardGroup>
