---
title: "Import from Calendly with one pasted personal access token"
method: POST
path: "/api/import/calendly"
tags: ["Import"]
---

# Import from Calendly with one pasted personal access token

`POST /api/import/calendly`

## Request

- Base URL: `https://whenmeet.me`
- URL: `https://whenmeet.me/api/import/calendly`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `__Host-session`

The token is used for this request only — never stored or logged. Preview reads the user schedule and bounded event-specific availability; personal links can keep their own weekly hours even when the profile was edited. apply: true creates selected new links and updates an untouched profile. Existing slugs are skipped without overwriting them. skipped lists whole links; warnings separately lists unavailable or converted settings before and after apply, including Calendly notice and horizon defaults.

## Request body

- object
  - `token` string, required: Calendly personal access token ("Bearer " prefix tolerated).
  - `apply` boolean
  - `slugs` string[]: Subset to import (default: all importable).

## Response `200`

Preview (ImportPreview) or, with apply, ImportResult.

- union
  - ImportPreview
    - `profile` object
      - `handle` string, nullable: Suggested nickname (with -1, -2 … if taken).
      - `displayName` string, nullable
      - `timezone` string, nullable
      - `weeklyHours` WeeklyHours: Working hours per weekday in the profile timezone, or in hoursTimezone for a personal link override: up to 6 ["HH:MM","HH:MM"] intervals per day ("24:00" allowed as an end). Missing days mean no hours; overlapping intervals merge. Profile default Mon–Fri 09:00–17:00.
        - `mon` array[]
          - string[]
        - `tue` array[]
          - string[]
        - `wed` array[]
          - string[]
        - `thu` array[]
          - string[]
        - `fri` array[]
          - string[]
        - `sat` array[]
          - string[]
        - `sun` array[]
          - string[]
    - `applyProfile` boolean: true while your auto-created profile is untouched — apply will then take over nickname, zone and hours.
    - `eventTypes` EventTypeInput[]
      - `title` string
      - `slug` string: Default: from the title (-2, -3 … appended if taken).
      - `description` string, nullable
      - `durationMin` integer
      - `conference` 'meet' | 'teams' | 'null', nullable: Default: meet for a Google calendar, teams for Microsoft.
      - `bufferBeforeMin` integer
      - `bufferAfterMin` integer
      - `minNoticeMin` integer
      - `maxDaysAhead` integer
      - `slotStepMin` 5 | 10 | 15 | 20 | 30 | 45 | 60 | 90 | 120
      - `dailyLimit` integer, nullable
      - `questions` BookingQuestion[]: Name and email are always collected.
        - `id` string, required
        - `label` string, required
        - `type` 'text' | 'textarea', required
        - `required` boolean, required
      - `weeklyHours` WeeklyHours: Working hours per weekday in the profile timezone, or in hoursTimezone for a personal link override: up to 6 ["HH:MM","HH:MM"] intervals per day ("24:00" allowed as an end). Missing days mean no hours; overlapping intervals merge. Profile default Mon–Fri 09:00–17:00.
        - `mon` array[]
          - string[]
        - `tue` array[]
          - string[]
        - `wed` array[]
          - string[]
        - `thu` array[]
          - string[]
        - `fri` array[]
          - string[]
        - `sat` array[]
          - string[]
        - `sun` array[]
          - string[]
      - `hoursTimezone` string, nullable: IANA timezone for weeklyHours. A non-null weeklyHours needs a valid non-null zone; clear both to follow the profile (invalid_hours_timezone on a mismatched pair).
      - `reminders` integer[]: Reminder emails to the invitee and guests, in minutes before the start (24 h and 1 h by default). Any 3 of the allowed values; duplicates collapse, stored sorted descending. [] turns reminders off; null resets to the default. Error: invalid_reminders.
      - `active` boolean
      - `team` TeamSettings: Turns a link into a TEAM link. mode "all" = every member must be free (e.g. a two-person interview panel); "any" = whoever is free, assigned in turn (round-robin). Members get an email invite and join with one calendar connect.
        - `mode` 'all' | 'any', required
        - `members` string[]: Colleagues to invite (you excluded).
        - `includeMe` boolean: You attend / can be assigned too. Default true.
      - `teamHandle` string, nullable: Team links only: the link’s own public address, whenmeet.me/@<teamHandle> (same rules as nicknames and the same namespace; a leading @ and upper case are forgiven). null or "" releases it; turning the link personal releases it too. Errors: invalid_team_handle (bad handle, or the link is / becomes personal), 409 handle_taken (held by any nickname — yours included — or another link; nothing changes), 400 too_many_team_handles (you already hold 5 team handles on other links; nothing changes).
      - `teamName` string, nullable: Shown with the team handle ("Acme Sales"); null → the link title. Stored only next to a team handle (ignored without one). Error: invalid_team_name.
    - `skipped` ImportFinding[]: Whole links or types not imported, with a reason.
      - `name` string, required
      - `code` 'invalid_settings' | 'slug_taken' | 'one_off' | 'meeting_poll' | 'round_robin' | 'collective' | 'team_event' | 'group_event' | 'secret_event' | 'inactive' | 'group_link' | 'unsupported_link_type' | 'availability_scope_missing' | 'too_many_links' | 'event_hours_unrepresentable' | 'event_hours_no_rule' | 'event_hours_unreadable' | 'calendly_multiple_durations' | 'calendly_duration_rounded' | 'name_shortened' | 'description_shortened' | 'questions_shortened' | 'questions_free_text' | 'multiple_locations' | 'video_provider_not_copied' | 'location_not_copied' | 'no_location' | 'date_exceptions_not_imported' | 'intervals_unrepresentable' | 'calendly_no_duration' | 'calendly_defaults' | 'buffer_unrepresentable' | 'step_unrepresentable' | 'horizon_unrepresentable' | 'hubspot_description_shortened' | 'hubspot_fields_unrepresentable' | 'hubspot_fields_omitted' | 'hubspot_labels_shortened' | 'hubspot_choice_free_text' | 'hubspot_location_not_copied' | 'hubspot_consent_not_copied' | 'hubspot_multiple_durations' | 'hubspot_duration_rounded' | 'hubspot_details_unavailable' | 'hubspot_no_duration' | 'hubspot_custom_availability' | 'hubspot_availability_undocumented' | 'hubspot_date_range_not_imported' | 'hubspot_defaults', required: Stable machine code. Skipped: invalid_settings {error}, slug_taken {slug}, one_off, meeting_poll, round_robin, collective, team_event, group_event, secret_event, inactive, group_link, unsupported_link_type, availability_scope_missing, too_many_links {max}. Warnings: everything else; *_multiple_durations {durations, to}, *_duration_rounded {from, to}, calendly_defaults / hubspot_defaults {settings}.
      - `params` object: Values for the message. error (invalid_settings) is the untranslated event-type validation code, e.g. invalid_duration_min. settings is a comma-separated list of setting codes: setting_notice, setting_horizon, setting_buffers, setting_buffer, setting_step, setting_daily_limit, setting_reminders.
      - `reason` string, required: English text (kept for compatibility).
    - `warnings` ImportFinding[]: Settings changed, approximated or unavailable for review before applying; separate from skipped links.
      - `name` string, required
      - `code` 'invalid_settings' | 'slug_taken' | 'one_off' | 'meeting_poll' | 'round_robin' | 'collective' | 'team_event' | 'group_event' | 'secret_event' | 'inactive' | 'group_link' | 'unsupported_link_type' | 'availability_scope_missing' | 'too_many_links' | 'event_hours_unrepresentable' | 'event_hours_no_rule' | 'event_hours_unreadable' | 'calendly_multiple_durations' | 'calendly_duration_rounded' | 'name_shortened' | 'description_shortened' | 'questions_shortened' | 'questions_free_text' | 'multiple_locations' | 'video_provider_not_copied' | 'location_not_copied' | 'no_location' | 'date_exceptions_not_imported' | 'intervals_unrepresentable' | 'calendly_no_duration' | 'calendly_defaults' | 'buffer_unrepresentable' | 'step_unrepresentable' | 'horizon_unrepresentable' | 'hubspot_description_shortened' | 'hubspot_fields_unrepresentable' | 'hubspot_fields_omitted' | 'hubspot_labels_shortened' | 'hubspot_choice_free_text' | 'hubspot_location_not_copied' | 'hubspot_consent_not_copied' | 'hubspot_multiple_durations' | 'hubspot_duration_rounded' | 'hubspot_details_unavailable' | 'hubspot_no_duration' | 'hubspot_custom_availability' | 'hubspot_availability_undocumented' | 'hubspot_date_range_not_imported' | 'hubspot_defaults', required: Stable machine code. Skipped: invalid_settings {error}, slug_taken {slug}, one_off, meeting_poll, round_robin, collective, team_event, group_event, secret_event, inactive, group_link, unsupported_link_type, availability_scope_missing, too_many_links {max}. Warnings: everything else; *_multiple_durations {durations, to}, *_duration_rounded {from, to}, calendly_defaults / hubspot_defaults {settings}.
      - `params` object: Values for the message. error (invalid_settings) is the untranslated event-type validation code, e.g. invalid_duration_min. settings is a comma-separated list of setting codes: setting_notice, setting_horizon, setting_buffers, setting_buffer, setting_step, setting_daily_limit, setting_reminders.
      - `reason` string, required: English text (kept for compatibility).
  - ImportResult
    - `created` EventType[]
      - `id` string
      - `slug` string
      - `title` string
      - `description` string, nullable
      - `durationMin` integer
      - `conference` 'meet' | 'teams' | 'null', nullable
      - `bufferBeforeMin` integer
      - `bufferAfterMin` integer
      - `minNoticeMin` integer
      - `maxDaysAhead` integer
      - `slotStepMin` integer
      - `dailyLimit` integer, nullable
      - `questions` BookingQuestion[]
        - `id` string, required
        - `label` string, required
        - `type` 'text' | 'textarea', required
        - `required` boolean, required
      - `weeklyHours` WeeklyHours: Working hours per weekday in the profile timezone, or in hoursTimezone for a personal link override: up to 6 ["HH:MM","HH:MM"] intervals per day ("24:00" allowed as an end). Missing days mean no hours; overlapping intervals merge. Profile default Mon–Fri 09:00–17:00.
        - `mon` array[]
          - string[]
        - `tue` array[]
          - string[]
        - `wed` array[]
          - string[]
        - `thu` array[]
          - string[]
        - `fri` array[]
          - string[]
        - `sat` array[]
          - string[]
        - `sun` array[]
          - string[]
      - `hoursTimezone` string, nullable: Timezone for the personal link’s weeklyHours override; null when following the profile.
      - `reminders` integer[]: Minutes before the start, sorted descending; [] = off.
      - `active` boolean
      - `position` integer
      - `url` string, uri: Public booking URL, e.g. https://whenmeet.me/@anna/intro
      - `team` object, nullable
        - `mode` 'all' | 'any'
        - `members` TeamMember[]
          - `email` string, email
          - `name` string, nullable
          - `status` 'pending' | 'active' | 'declined'
          - `isOwner` boolean
          - `visibility` 'self' | 'org' | 'none': self = joined, their own calendar is used; org = not joined yet but your calendar account can see their free/busy (same Workspace / Microsoft 365 org); none = not visible until they join (excluded from the check).
          - `hours` ParticipantHours: The working hours a team participant is checked against (owner view only — never public). Every teammate is checked against their OWN hours: own = their booking profile (also your own entry); default = joined but no profile yet: Mon–Fri 09:00–17:00 in their account timezone (UTC if unknown); owner = not joined yet (pending / declined): your hours and zone.
            - `weeklyHours` WeeklyHours, required: Working hours per weekday in the profile timezone, or in hoursTimezone for a personal link override: up to 6 ["HH:MM","HH:MM"] intervals per day ("24:00" allowed as an end). Missing days mean no hours; overlapping intervals merge. Profile default Mon–Fri 09:00–17:00.
              - …
            - `tz` string, required: IANA zone the hours are in.
            - `source` 'own' | 'default' | 'owner', required
        - `health` TeamHealth: Can this team link take bookings right now? The same strict calendar read the public page does (today in the link zone + 14 days), served from its 60 s cache. Inactive links are not read and report ok.
          - `ok` boolean, required
          - `reason` 'member_unreadable' | 'no_checkable_member' | 'null', nullable, required: member_unreadable = an "all" participant, or every "any" participant, can’t be read (an "any" link with only some unreadable stays ok); no_checkable_member = nobody can be checked, or you have no calendar connected.
          - `memberEmail` string, nullable, required: The first unreadable participant (member_unreadable only).
      - `teamHandle` string, nullable: The team link’s own handle (null for personal links and team links without one).
      - `teamName` string, nullable
      - `teamUrl` string, uri, nullable: https://whenmeet.me/@<teamHandle>, or null.
    - `skipped` ImportFinding[]
      - `name` string, required
      - `code` 'invalid_settings' | 'slug_taken' | 'one_off' | 'meeting_poll' | 'round_robin' | 'collective' | 'team_event' | 'group_event' | 'secret_event' | 'inactive' | 'group_link' | 'unsupported_link_type' | 'availability_scope_missing' | 'too_many_links' | 'event_hours_unrepresentable' | 'event_hours_no_rule' | 'event_hours_unreadable' | 'calendly_multiple_durations' | 'calendly_duration_rounded' | 'name_shortened' | 'description_shortened' | 'questions_shortened' | 'questions_free_text' | 'multiple_locations' | 'video_provider_not_copied' | 'location_not_copied' | 'no_location' | 'date_exceptions_not_imported' | 'intervals_unrepresentable' | 'calendly_no_duration' | 'calendly_defaults' | 'buffer_unrepresentable' | 'step_unrepresentable' | 'horizon_unrepresentable' | 'hubspot_description_shortened' | 'hubspot_fields_unrepresentable' | 'hubspot_fields_omitted' | 'hubspot_labels_shortened' | 'hubspot_choice_free_text' | 'hubspot_location_not_copied' | 'hubspot_consent_not_copied' | 'hubspot_multiple_durations' | 'hubspot_duration_rounded' | 'hubspot_details_unavailable' | 'hubspot_no_duration' | 'hubspot_custom_availability' | 'hubspot_availability_undocumented' | 'hubspot_date_range_not_imported' | 'hubspot_defaults', required: Stable machine code. Skipped: invalid_settings {error}, slug_taken {slug}, one_off, meeting_poll, round_robin, collective, team_event, group_event, secret_event, inactive, group_link, unsupported_link_type, availability_scope_missing, too_many_links {max}. Warnings: everything else; *_multiple_durations {durations, to}, *_duration_rounded {from, to}, calendly_defaults / hubspot_defaults {settings}.
      - `params` object: Values for the message. error (invalid_settings) is the untranslated event-type validation code, e.g. invalid_duration_min. settings is a comma-separated list of setting codes: setting_notice, setting_horizon, setting_buffers, setting_buffer, setting_step, setting_daily_limit, setting_reminders.
      - `reason` string, required: English text (kept for compatibility).
    - `warnings` ImportFinding[]: Setting-level differences to review on the imported links.
      - `name` string, required
      - `code` 'invalid_settings' | 'slug_taken' | 'one_off' | 'meeting_poll' | 'round_robin' | 'collective' | 'team_event' | 'group_event' | 'secret_event' | 'inactive' | 'group_link' | 'unsupported_link_type' | 'availability_scope_missing' | 'too_many_links' | 'event_hours_unrepresentable' | 'event_hours_no_rule' | 'event_hours_unreadable' | 'calendly_multiple_durations' | 'calendly_duration_rounded' | 'name_shortened' | 'description_shortened' | 'questions_shortened' | 'questions_free_text' | 'multiple_locations' | 'video_provider_not_copied' | 'location_not_copied' | 'no_location' | 'date_exceptions_not_imported' | 'intervals_unrepresentable' | 'calendly_no_duration' | 'calendly_defaults' | 'buffer_unrepresentable' | 'step_unrepresentable' | 'horizon_unrepresentable' | 'hubspot_description_shortened' | 'hubspot_fields_unrepresentable' | 'hubspot_fields_omitted' | 'hubspot_labels_shortened' | 'hubspot_choice_free_text' | 'hubspot_location_not_copied' | 'hubspot_consent_not_copied' | 'hubspot_multiple_durations' | 'hubspot_duration_rounded' | 'hubspot_details_unavailable' | 'hubspot_no_duration' | 'hubspot_custom_availability' | 'hubspot_availability_undocumented' | 'hubspot_date_range_not_imported' | 'hubspot_defaults', required: Stable machine code. Skipped: invalid_settings {error}, slug_taken {slug}, one_off, meeting_poll, round_robin, collective, team_event, group_event, secret_event, inactive, group_link, unsupported_link_type, availability_scope_missing, too_many_links {max}. Warnings: everything else; *_multiple_durations {durations, to}, *_duration_rounded {from, to}, calendly_defaults / hubspot_defaults {settings}.
      - `params` object: Values for the message. error (invalid_settings) is the untranslated event-type validation code, e.g. invalid_duration_min. settings is a comma-separated list of setting codes: setting_notice, setting_horizon, setting_buffers, setting_buffer, setting_step, setting_daily_limit, setting_reminders.
      - `reason` string, required: English text (kept for compatibility).
    - `profile` Profile
      - `handle` string
      - `displayName` string, nullable
      - `welcome` string, nullable: Intro shown on the public page.
      - `timezone` string: IANA zone the weekly hours are expressed in.
      - `weeklyHours` WeeklyHours: Working hours per weekday in the profile timezone, or in hoursTimezone for a personal link override: up to 6 ["HH:MM","HH:MM"] intervals per day ("24:00" allowed as an end). Missing days mean no hours; overlapping intervals merge. Profile default Mon–Fri 09:00–17:00.
        - `mon` array[]
          - string[]
        - `tue` array[]
          - string[]
        - `wed` array[]
          - string[]
        - `thu` array[]
          - string[]
        - `fri` array[]
          - string[]
        - `sat` array[]
          - string[]
        - `sun` array[]
          - string[]
      - `createdAt` integer: unix ms
      - `updatedAt` integer: unix ms

## Other responses

- `400`: invalid_token | calendly_unauthorized | calendly_scope_missing (the PAT needs users:read, event_types:read, availability:read).
- `401`: unauthenticated (no session or token), or invalid_token (a Bearer token that is malformed, unknown or revoked — never a silent anonymous fallback).
- `429`: calendly_rate_limited.
- `500`: import_failed.
- `502`: calendly_failed.

---

[API](https://skmtc.dev/whenmeet/apis/whenmeet-me-api.md) · [All operations](https://skmtc.dev/whenmeet/apis/whenmeet-me-api/llms.txt) · [OpenAPI document](https://skmtc.dev/whenmeet/apis/whenmeet-me-api/revisions/202b80022215?raw)
