> ## 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.

# Create Meeting Type

> Create a new meeting type for bookings

Create a new meeting type that defines the rules for a type of meeting, such as its title and duration.

## Endpoint

```
POST /v4/meeting-type
```

## Request Headers

| Header                   | Required | Description                                |
| ------------------------ | -------- | ------------------------------------------ |
| `Authorization`          | Yes      | `Bearer <your-api-key>`                    |
| `x-meetergo-api-user-id` | Yes      | UUID of the user who owns the meeting type |
| `Content-Type`           | Yes      | `application/json`                         |

## Request Body

| Field            | Type      | Required | Description                                                                                        |
| ---------------- | --------- | -------- | -------------------------------------------------------------------------------------------------- |
| `meetingInfo`    | object    | Yes      | Core meeting configuration                                                                         |
| `meetingOptions` | object    | No       | Meeting options (channels, channel availability, etc.)                                             |
| `slug`           | string    | No       | URL-friendly identifier (auto-generated if omitted)                                                |
| `availabilityId` | string    | No       | ID of existing availability to use                                                                 |
| `availability`   | object    | No       | Create new availability inline (mutually exclusive with `availabilityId`)                          |
| `locations`      | string\[] | No       | Address(es) for in-person meetings. When multiple locations are provided, the attendee can choose. |
| `ics`            | object    | No       | Calendar invite settings (title, description, location). See [ics](#ics).                          |
| `metadata`       | object    | No       | Key-value pairs for external system correlation                                                    |
| `options`        | object    | No       | Request options (e.g., `createOneTimeLink`)                                                        |

### meetingInfo (required)

| Field               | Type   | Required | Description                                                                                               |
| ------------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------- |
| `name`              | string | Yes      | Display name for the meeting type                                                                         |
| `description`       | string | Yes      | Description shown on booking page                                                                         |
| `duration`          | number | Yes      | Duration in minutes                                                                                       |
| `channel`           | string | Yes      | `google`, `zoom`, `teamsForBusiness2`, `phone`, `local`, `whereby`, `custom`, `connect`, `webex`, `jitsi` |
| `bufferBefore`      | number | No       | Minutes blocked before meeting (default: 0)                                                               |
| `bufferAfter`       | number | No       | Minutes blocked after meeting (default: 0)                                                                |
| `color`             | string | No       | Color in RGB format, e.g. `rgb(0, 153, 255)`                                                              |
| `customChannelName` | string | No       | Display label for a custom meeting channel (used when `channel` is `custom`)                              |
| `customChannelLink` | string | No       | URL for the custom meeting channel (required when `channel` is `custom`)                                  |

### meetingOptions

| Field                   | Type      | Required | Description                                                                                                                                                                                                  |
| ----------------------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `allowedChannels`       | string\[] | No       | Channel options the attendee can choose from (e.g., `["zoom", "phone", "local"]`). When more than one channel is provided, channel selection is automatically enabled on the booking page.                   |
| `channelAvailabilities` | object    | No       | Per-channel availability overrides. Each key is a channel name, each value is a UUID string (existing availability) or an inline availability object. See [Channel Availabilities](#channel-availabilities). |
| `allowedDurations`      | number\[] | No       | Additional duration options in minutes (shown alongside the primary duration)                                                                                                                                |
| `allowAddingGuests`     | boolean   | No       | Allow attendees to invite additional guests                                                                                                                                                                  |
| `allowPhoneOnlyBooking` | boolean   | No       | Allow bookings without attendee email (phone as identifier). For voice AI / phone scheduling use cases. See [Voice AI Bot](/developer-docs/recipes/voice-ai-bot)                                             |
| `doubleOptIn`           | string    | No       | Double opt-in setting: `useCompanySettings`, `enabled`, `disabled`                                                                                                                                           |

### channelAvailabilities

Override the default availability for specific channels. Each value can be:

* A **UUID string** referencing an existing availability
* An **inline availability object** (same structure as top-level `availability`) that will be created automatically

```json theme={null}
{
  "channelAvailabilities": {
    "phone": "existing-availability-uuid",
    "local": {
      "name": "In-Person Hours",
      "timezone": "Europe/Berlin",
      "schedule": {
        "monday": { "enabled": true, "hours": [{ "start": "10:00", "end": "16:00" }] },
        "tuesday": { "enabled": true, "hours": [{ "start": "10:00", "end": "16:00" }] },
        "wednesday": { "enabled": false, "hours": [] },
        "thursday": { "enabled": false, "hours": [] },
        "friday": { "enabled": false, "hours": [] },
        "saturday": { "enabled": false, "hours": [] },
        "sunday": { "enabled": false, "hours": [] }
      }
    }
  }
}
```

Channels not included in `channelAvailabilities` use the meeting type's default availability.

<Tip>
  Omit `schedule` from an inline availability object to create an exceptions-only availability (all days disabled by default). This is useful for channels available only at specific times.
</Tip>

### availability

Create availability inline instead of referencing an existing `availabilityId`. Uses the same structure as the [Availability API](/developer-docs/core-concepts/availability).

| Field        | Type   | Required | Description                                                                                                                                 |
| ------------ | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`       | string | Yes      | Name for the availability schedule                                                                                                          |
| `timezone`   | string | Yes      | IANA timezone (e.g., `Europe/Berlin`)                                                                                                       |
| `schedule`   | object | No       | Weekly recurring schedule ([format](/developer-docs/core-concepts/availability#schedule-format)). If omitted, all days default to disabled. |
| `exceptions` | array  | No       | Date-specific overrides ([format](/developer-docs/core-concepts/availability#exceptions-only-availability))                                 |

<Tip>
  For ticket-based scheduling with specific time slots, omit `schedule` and use only `exceptions`. See [Exceptions-Only Availability](/developer-docs/core-concepts/availability#exceptions-only-availability).
</Tip>

### metadata

Key-value pairs for integration with external systems. Included in webhook payloads.

| Constraint       | Limit          |
| ---------------- | -------------- |
| Max keys         | 20             |
| Max value length | 500 characters |
| Value type       | String only    |

### ics

Customize the calendar invite (ICS) that attendees and hosts receive. Each field accepts either a **plain string** or a **multi-language object**. If omitted, sensible defaults are used.

| Field         | Type             | Description                         |
| ------------- | ---------------- | ----------------------------------- |
| `title`       | string \| object | Calendar event title template       |
| `description` | string \| object | Calendar event description template |
| `location`    | string \| object | Calendar event location template    |

When you pass a **plain string**, it is stored under the company's default language. When you pass an **object**, each key is a language code (e.g. `en`, `de`) mapping to the template for that language.

Use dynamic tags as placeholders — they are replaced with actual values when the calendar invite is generated. See [Update Meeting Type - Dynamic Tags](/api-reference/meeting-types/update-meeting-type#dynamic-tags) for the full list.

### options

| Field               | Type    | Description                               |
| ------------------- | ------- | ----------------------------------------- |
| `createOneTimeLink` | boolean | Create and return a one-time booking link |

## Examples

### Basic Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.meetergo.com/v4/meeting-type" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "x-meetergo-api-user-id: 550e8400-e29b-41d4-a716-446655440000" \
    -H "Content-Type: application/json" \
    -d '{
      "meetingInfo": {
        "name": "Quick 15min Chat",
        "description": "A quick call to discuss your questions",
        "duration": 15,
        "channel": "google"
      },
      "slug": "quick-chat"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.meetergo.com/v4/meeting-type', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'x-meetergo-api-user-id': '550e8400-e29b-41d4-a716-446655440000',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      meetingInfo: {
        name: 'Quick 15min Chat',
        description: 'A quick call to discuss your questions',
        duration: 15,
        channel: 'google'
      },
      slug: 'quick-chat'
    })
  });

  const meetingType = await response.json();
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.meetergo.com/v4/meeting-type',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'x-meetergo-api-user-id': '550e8400-e29b-41d4-a716-446655440000',
          'Content-Type': 'application/json'
      },
      json={
          'meetingInfo': {
              'name': 'Quick 15min Chat',
              'description': 'A quick call to discuss your questions',
              'duration': 15,
              'channel': 'google'
          },
          'slug': 'quick-chat'
      }
  )

  meeting_type = response.json()
  ```
</CodeGroup>

### With Buffers

```json theme={null}
{
  "meetingInfo": {
    "name": "Product Demo",
    "description": "A 45-minute walkthrough of our product features",
    "duration": 45,
    "channel": "zoom",
    "bufferBefore": 15,
    "bufferAfter": 10
  },
  "slug": "product-demo"
}
```

### With Custom Channel

```json theme={null}
{
  "meetingInfo": {
    "name": "Webinar Session",
    "description": "Join our interactive webinar",
    "duration": 60,
    "channel": "custom",
    "customChannelName": "Company Webinar Platform",
    "customChannelLink": "https://webinar.example.com/room/abc123"
  }
}
```

### With In-Person Location

```json theme={null}
{
  "meetingInfo": {
    "name": "Office Consultation",
    "description": "In-person meeting at our office",
    "duration": 45,
    "channel": "local"
  },
  "locations": ["123 Main St, Suite 200, Berlin"]
}
```

When multiple locations are provided, the attendee can choose on the booking page:

```json theme={null}
{
  "meetingInfo": {
    "name": "On-Site Visit",
    "description": "Meet us at one of our offices",
    "duration": 60,
    "channel": "local"
  },
  "locations": ["Berlin Office - Friedrichstr. 123", "Munich Office - Marienplatz 5"]
}
```

### With Metadata

Store custom data for integration with external systems:

```json theme={null}
{
  "meetingInfo": {
    "name": "Property Evaluation",
    "description": "On-site property evaluation",
    "duration": 60,
    "channel": "phone"
  },
  "metadata": {
    "ticketId": "EVAL-12345",
    "propertyAddress": "123 Main St",
    "source": "crm-integration"
  }
}
```

### With Specific Time Slots (Exceptions Only)

Create availability with specific datetime slots only—no recurring weekly schedule:

```json theme={null}
{
  "meetingInfo": {
    "name": "Ticket Consultation",
    "description": "One-time consultation for ticket #12345",
    "duration": 60,
    "channel": "phone"
  },
  "availability": {
    "name": "Ticket Availability",
    "timezone": "Europe/Berlin",
    "exceptions": [
      { "available": true, "start": "2026-01-27T10:00", "end": "2026-01-27T11:00" },
      { "available": true, "start": "2026-01-27T14:00", "end": "2026-01-27T15:00" },
      { "available": true, "start": "2026-01-28T09:00", "end": "2026-01-28T10:00" }
    ]
  },
  "metadata": {
    "ticketId": "EVAL-12345"
  }
}
```

<Note>
  When `schedule` is omitted from `availability`, the weekly schedule defaults to all days disabled. Only the specified `exceptions` define available booking windows.
</Note>

### With One-Time Link

Create a meeting type with a one-time booking link in a single API call:

```json theme={null}
{
  "meetingInfo": {
    "name": "Scheduled Callback",
    "description": "One-time callback for support case",
    "duration": 30,
    "channel": "phone"
  },
  "availability": {
    "name": "Callback Availability",
    "timezone": "Europe/Berlin",
    "exceptions": [
      { "available": true, "start": "2026-01-27T10:00", "end": "2026-01-27T11:00" }
    ]
  },
  "metadata": {
    "caseId": "CASE-789"
  },
  "options": {
    "createOneTimeLink": true
  }
}
```

### With Multiple Channels and Channel Availabilities

Create a meeting type where the attendee can choose between channels, each with its own availability:

```json theme={null}
{
  "meetingInfo": {
    "name": "Sales Call",
    "description": "Choose your preferred meeting format",
    "duration": 30,
    "channel": "zoom"
  },
  "meetingOptions": {
    "allowedChannels": ["zoom", "phone", "local"],
    "channelAvailabilities": {
      "phone": "660e8400-e29b-41d4-a716-446655440001",
      "local": {
        "name": "In-Person Hours",
        "timezone": "Europe/Berlin",
        "schedule": {
          "monday": { "enabled": true, "hours": [{ "start": "10:00", "end": "16:00" }] },
          "tuesday": { "enabled": true, "hours": [{ "start": "10:00", "end": "16:00" }] },
          "wednesday": { "enabled": false, "hours": [] },
          "thursday": { "enabled": false, "hours": [] },
          "friday": { "enabled": false, "hours": [] },
          "saturday": { "enabled": false, "hours": [] },
          "sunday": { "enabled": false, "hours": [] }
        }
      },
      "zoom": {
        "name": "No Zoom Fridays",
        "timezone": "Europe/Berlin",
        "exceptions": [
          { "available": false, "start": "2026-03-07T00:00", "end": "2026-03-07T23:59", "title": "No Zoom Friday" }
        ]
      }
    }
  },
  "availability": {
    "name": "Default Schedule",
    "timezone": "Europe/Berlin",
    "schedule": {
      "monday": { "enabled": true, "hours": [{ "start": "09:00", "end": "17:00" }] },
      "tuesday": { "enabled": true, "hours": [{ "start": "09:00", "end": "17:00" }] },
      "wednesday": { "enabled": true, "hours": [{ "start": "09:00", "end": "17:00" }] },
      "thursday": { "enabled": true, "hours": [{ "start": "09:00", "end": "17:00" }] },
      "friday": { "enabled": true, "hours": [{ "start": "09:00", "end": "17:00" }] },
      "saturday": { "enabled": false, "hours": [] },
      "sunday": { "enabled": false, "hours": [] }
    }
  }
}
```

<Note>
  When `allowedChannels` has more than one entry, channel selection is automatically enabled on the booking page. You don't need to set `allowSelectChannel` explicitly.
</Note>

## Response

### Success (201 Created)

```json theme={null}
{
  "id": "770e8400-e29b-41d4-a716-446655440002",
  "slug": "quick-chat",
  "meetingInfo": {
    "name": "Quick 15min Chat",
    "description": "A quick call to discuss your questions",
    "duration": 15,
    "channel": "google"
  },
  "bookingUrl": "https://cal.meetergo.com/john-smith/quick-chat",
  "createdAt": "2024-01-15T10:30:00Z"
}
```

### With metadata and oneTimeLink

When `options.createOneTimeLink` is `true`:

```json theme={null}
{
  "id": "770e8400-e29b-41d4-a716-446655440002",
  "slug": "property-evaluation-abc123",
  "meetingInfo": {
    "name": "Property Evaluation",
    "description": "On-site property evaluation",
    "duration": 60,
    "channel": "phone"
  },
  "bookingUrl": "https://cal.meetergo.com/john-smith/property-evaluation-abc123",
  "metadata": {
    "ticketId": "EVAL-12345",
    "source": "crm-integration"
  },
  "availabilityId": "880e8400-e29b-41d4-a716-446655440003",
  "oneTimeLink": {
    "id": "abc123xyz",
    "url": "https://cal.meetergo.com/1t/abc123xyz",
    "meetingTypeId": "770e8400-e29b-41d4-a716-446655440002"
  },
  "createdAt": "2024-01-15T10:30:00Z"
}
```

| Field                  | Description                                                     |
| ---------------------- | --------------------------------------------------------------- |
| `id`                   | UUID of the created meeting type                                |
| `slug`                 | URL-friendly identifier                                         |
| `meetingInfo`          | Core meeting configuration                                      |
| `meetingInfo.name`     | Display name                                                    |
| `meetingInfo.duration` | Duration in minutes                                             |
| `meetingInfo.channel`  | Meeting channel type                                            |
| `bookingUrl`           | Public booking URL                                              |
| `metadata`             | Custom key-value data (if provided)                             |
| `availabilityId`       | ID of created availability (if `availability` was provided)     |
| `oneTimeLink`          | One-time link details (if `options.createOneTimeLink` was true) |
| `oneTimeLink.url`      | Full URL for the one-time booking page                          |
| `createdAt`            | Creation timestamp                                              |

### Error Responses

#### 400 Bad Request - Validation Error

```json theme={null}
{
  "statusCode": 400,
  "message": "Validation failed",
  "errors": [
    {
      "field": "duration",
      "message": "Duration must be a positive number"
    }
  ]
}
```

#### 409 Conflict - Slug Already Exists

```json theme={null}
{
  "statusCode": 409,
  "message": "A meeting type with this slug already exists",
  "error": "Conflict"
}
```

## Common Durations

| Duration | Use Case                                 |
| -------- | ---------------------------------------- |
| 15 min   | Quick check-ins, brief consultations     |
| 30 min   | Standard meetings, initial calls         |
| 45 min   | Discovery calls, demos                   |
| 60 min   | Deep-dive sessions, workshops            |
| 90 min   | Training sessions, comprehensive reviews |

## Related Endpoints

<CardGroup cols={2}>
  <Card title="List Meeting Types" icon="list" href="/api-reference/meeting-types/list-meeting-types">
    Get all meeting types for a user
  </Card>

  <Card title="Update Meeting Type" icon="pen" href="/api-reference/meeting-types/update-meeting-type">
    Modify an existing meeting type
  </Card>

  <Card title="Delete Meeting Type" icon="trash" href="/api-reference/meeting-types/delete-meeting-type">
    Soft delete a meeting type
  </Card>
</CardGroup>
