Booking with Calendly
Set up Calendly booking in Simple, Connected, or Advanced mode — tokens, event types, locations, custom questions, and what the errors mean.
This page is the Calendly-specific companion to Configuring an action: which mode to pick, exactly what Calendly asks for in each, what happens during a live booking, and what the errors mean. Using Cal.com instead? See Booking with Cal.com.
Pick a mode
| Mode | You provide | Visitors get | Calendly plan |
|---|---|---|---|
| Simple | Your public booking-page link | Calendly's calendar embedded in the chat | Any (free works) |
| Connected | One-click OAuth (no key to copy) | In-chat calendar plus tappable live slots | Any (free works) |
| Advanced | Personal access token + event type | Instant in-conversation booking by the agent | Paid for instant booking; free falls back to a scheduling link |
On a free Calendly plan, Simple or Connected mode is the better fit — both give visitors the full in-chat calendar with no token, while Advanced on a free plan degrades to handing out a scheduling link (Calendly's Scheduling API is paid-only).
Simple mode
Paste your public booking-page URL — the same link you would send anyone, e.g. https://calendly.com/you/intro-call — into Your booking page link. The field confirms ✓ Calendly link as you type. No token, no verification call, works on any plan. The general behavior of the embedded calendar (what visitors see, messaging/voice fallbacks, the "Book a meeting" widget chip) is covered in Configuring an action.
Connected mode
Click Connect Calendly — Calendly's OAuth flow opens; approve it and you land back on the Actions tab shown as Connected as you@example.com. There is no API key to copy or paste in this mode; the token box on this screen is the Cal.com panel's, not Calendly's.
Once connected, pick an event type from the Event type dropdown and save. Visitors book in the in-chat calendar, and the agent can additionally read live open slots and offer them as tappable chips — tapping one opens the calendar pre-targeted at that time.
The connection is workspace-wide and holds one Calendly account: every chatbot books through it, and disconnecting stops live availability for all of them (the dashboard confirms with the count). Re-authorizing with a different Calendly login requires an explicit account-switch confirmation.
Advanced mode
Pick Provider → Calendly (scheduling link) and fill:
- Personal access token — Calendly → Integrations → API & Webhooks → Personal access tokens → Generate. Use the copy button, not hand-selection: a Calendly token is a long three-part string (it starts
eyJand contains two dots); a partial copy is the single most common cause of "token rejected". Paste it into API token / secret — it is stored in the encrypted vault and never shown to the model. - Calendly event type URI — easiest: paste the token, save, then click Load event types and pick from the dropdown. If you must build it by hand it is the event type's API resource URI,
https://api.calendly.com/event_types/<uuid>— see troubleshooting for the uuid pitfalls.
Saving an enabled action verifies both against Calendly live; a definitive rejection blocks the save with a message naming which one failed.
Turn off invitee email verification for the event type. If the event type requires invitees to verify their email with a 6-digit code (Calendly → Settings → Privacy, per event type), Calendly refuses every API booking — there is no way for the chat agent to complete the code step, so visitors always get the scheduling-link fallback instead of an instant booking. Disable verification on event types you book through Advanced mode.
What happens during a booking
Advanced-mode booking runs through the confirm gate: the agent collects the visitor's name, email, and time (offering real open slots as tappable chips), reads the details back, and books only after the visitor confirms. Additionally, Calendly-specific behavior:
- Meeting location is handled for you. The booking mirrors whatever location the event type configures: Google Meet / Zoom / Teams conferences pass through and the invite carries the meeting link; a physical or custom address echoes the event type's own value; a "host calls the invitee" location uses the visitor's phone number (if they never volunteered one, the booking falls back to a scheduling link so Calendly can collect it).
- Custom questions are asked in the chat. If the event type has intake questions, the agent asks the visitor every required one before proposing the booking — a multiple-choice question is presented with its choices verbatim, and the answer must be one of them. The booking is not armed for confirmation until all required questions are answered, and the answers land on the Calendly booking like a normal form submission.
- Phone numbers: a volunteered
+-international number becomes the SMS reminder number. Never required, never blocks a booking. - Fallback: whenever the direct booking cannot complete — free plan, transient provider errors after three attempts, an unanswerable required question — the agent mints a single-use scheduling link and the visitor finishes there. Booking always completes one way or the other.
The visitor is never told the provider's name — the agent says "our scheduling system" (see Configuring an action).
Troubleshooting
"API token was rejected by Calendly"
Calendly returned a 401/403 for the token itself. In order of likelihood:
- 1Truncated copy. A real personal access token starts
eyJand contains two dots (header.payload.signature, several hundred characters). If yours has no dots, you copied only the first part — re-copy with the copy button. Quick check:echo "$TOKEN" | grep -o '\.' | wc -lmust print2. - 2Wrong kind of secret. An OAuth client secret or webhook signing key is not a personal access token.
- 3Revoked or wrong account. Regenerating a token kills the old one, and a token only sees its own account's event types.
Verify a token in one line:
curl -s -o /dev/null -w "%{http_code}\n" https://api.calendly.com/users/me \
-H "Authorization: Bearer $TOKEN" # 200 = token is fineThe event type URI is wrong
A valid token plus a wrong URI gives "That Calendly event type was not found on this account." Common mistakes:
- It's your user uuid. The uuid in your dashboard profile (and inside the token) identifies you, not an event type. Event type uuids are different.
- It's the list endpoint.
…/event_types?user=…lists event types; the field needs one specific…/event_types/<uuid>. - It's the public booking page.
calendly.com/you/intro-callbelongs in Simple mode, not here.
Skip all of that: click Load event types and pick from the dropdown. Or list them yourself:
curl -s "https://api.calendly.com/event_types?user=$(curl -s \
https://api.calendly.com/users/me -H "Authorization: Bearer $TOKEN" \
| jq -r '.resource.uri')" \
-H "Authorization: Bearer $TOKEN" | jq -r '.collection[].uri'Visitors get a link instead of an instant booking
Two common causes:
- Free Calendly plan — the Scheduling API needs a paid plan, so the agent falls back to the scheduling link. The dashboard warns about this at save time. Either upgrade, or switch to Simple/Connected mode for the full in-chat calendar.
- Invitee email verification is on for the event type — see the entry below; the action-run log names it explicitly.
"Calendly requires invitee email verification for this event type"
The event type has invitee email verification turned on, so Calendly rejects every booking made through the API — verification's 6-digit email code can only be entered on Calendly's own booking page. The visitor still gets the scheduling-link fallback and can finish (and verify) there, but instant in-chat booking will never succeed while it's on. Fix: Calendly → Settings → Privacy (admins: Settings → Security → Privacy), select the event type, Disable Verification.
Bookings fail with a location or questions error
Older versions did not send the event type's meeting location or required questions with the booking (Calendly rejects those bookings with "Specified location kind is not configured for this event type" / "Required Questions and Answers cannot be blank"). Both are handled automatically now — if you still see these in the action-run log, make sure the app is up to date.
Where to go next
Last updated