Calendly#
Calendly is registered for API sync with sync-coupled user import. It pulls scheduled events from the authenticated user's current Calendly organization into a reviewable import session, proposes TeamBoost user mappings from Calendly users and invitees, and projects each scheduled event into the internal integrations task-create draft for operator review.
| Capability | Method | Status |
|---|---|---|
SYNC |
Pull scheduled events from the Calendly API | Built |
USER_IMPORT |
Bring Calendly users and invitees into task-import mapping | Built as part of API sync |
CSV_IMPORT |
Upload a Calendly export | Not built |
WEBHOOK |
Verify Calendly webhook events | Not built |
The endpoints below live under /api/v1/providers/calendly/.... They are
generic: the same routes serve any registered provider by substituting the
{provider} path segment. All routes require an organization-scoped user token
(see Authentication).
Discovery#
GET /api/v1/providers/calendly
{
"status": "success",
"data": { "provider": "calendly", "capabilities": ["SYNC", "USER_IMPORT"] }
}
Credential Verification#
Calendly personal access tokens can be stored and verified for API sync:
PUT /api/v1/providers/calendly/credentials?organization_id=<id>
POST /api/v1/providers/calendly/credentials/verify?organization_id=<id>
The stored secret is the Calendly token string:
{ "secret": "<calendly-personal-access-token>" }
Verification sends the secret as a Calendly bearer token, fetches
GET /users/me, reads the current organization URI from the user resource, and
then probes GET /scheduled_events for that organization. A rejected token, a
token that does not expose a current organization, or missing API access for the
sync probe returns invalid_api_key. Stored secrets are encrypted at rest and
never returned by the credential endpoints.
Importing From The Calendly API#
POST /api/v1/providers/calendly/imports/sync?organization_id=<id>
Uses the stored encrypted Calendly token to fetch a bounded organization-scoped
scheduled-event window. The current generic sync endpoint has no
provider-specific request body, so the Calendly organization comes from the
token's current_organization value.
The first shipped sync window is intentionally bounded:
- 7 days in the past through 90 days in the future;
- organization-scoped scheduled events;
- active and canceled events when Calendly returns them;
- invitees fetched per scheduled event for mapping and review context.
The adapter calls:
GET https://api.calendly.com/users/meGET https://api.calendly.com/organization_memberships?organization=...GET https://api.calendly.com/scheduled_events?organization=...&min_start_time=...&max_start_time=...GET https://api.calendly.com/scheduled_events/{event_uuid}/invitees
Calendly collection pagination is followed. Rate limits (429) and transient
server failures are retried with bounded backoff. Invalid or revoked tokens and
missing-scope responses return credential errors.
User Mapping#
Calendly USER_IMPORT rides the sync flow. The adapter proposes mappings from:
- the authenticated Calendly user;
- users returned by
GET /organization_memberships; - scheduled-event hosts;
- scheduled-event invitees.
The primary matching key is the Calendly resource URI (sourceAccountId). Email
is secondary when present, then name. Invitees are imported for matching and
preserved as review context, but they are not automatically assigned as owners or
requesters.
Projection Field Coverage#
| Calendly source | TeamBoost draft field | Notes |
|---|---|---|
Scheduled-event name |
title |
Error if shorter than 2 characters |
| Scheduled event | type |
Meetings default to OTHER with a mapping note |
Event description |
description |
Passed through when present |
Event status |
status |
active maps to NOT_STARTED; canceled maps to CANCELED; unknown labels are left unset with a note |
| No native task priority | priority |
Defaults to UNKNOWN with a mapping note |
| First event membership | creatorId |
Resolved through the user mapping when possible |
| Invitees | ownerId |
Invitees are imported for user mapping but are not assigned as owners automatically |
| Invitees | requestedById |
Preserved in descriptionJson; requester mapping is left unset until the product rule is confirmed |
| Event start/end | plannedStartDate, estimatedStartDate, plannedEndDate |
Meeting length is not converted into TeamBoost effort duration |
| Calendly | projectTitle |
Defaults to Calendly |
| Event refs, invitees, location, calendar refs, cancellation, sync context | descriptionJson |
Preserved for review |
Not Built Yet#
- CSV import.
- OAuth app install flow.
- Standalone user-directory import before sync.
- Webhook registration and event verification.
- Provider-specific sync filters or persisted incremental sync state.
- Live Calendly PAT validation in this repo's automated tests; use a real Calendly owner/admin PAT and non-production organization for release smoke.