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


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.