Calendly
developer.calendly.com ↗Self-serve OAuth: register an app in Calendly's Developer tools in minutes with no review gate, but PKCE S256 is mandatory, each app gets exactly one redirect URI, and Production requires HTTPS.
01Pick your path
02Time & effort
- DEVAccount + Developer tools5–10 minutessourced[S5]Owner must be a real Calendly user; no review or business verification is documented for this step.
- DEVRegister sandbox OAuth app5–15 minutessourced[S5]App name, one redirect URI, environment type = Sandbox, at least one scope; credentials appear once.
- DEVImplement PKCE flow20–45 minutessourced[S5]Verifier/challenge generation, authorize redirect, token exchange at auth.calendly.com/oauth/token.
- DEVEnd-to-end consent test10–30 minutesinferred[S5]Needs a human to click through the consent screen; estimate is inferred, sources give no timing.
- PRODProduction app + credential swap5–15 minutessourced[S5]Production requires an https redirect URI; docs recommend a second app rather than editing the sandbox one.
03Steps
Get a working connection
Calendly → Profile menu → Developer → OAuth apps tab. If Developer is absent, your account is still migrating: use developer.calendly.com.
“Open Developer tools. In Calendly, open the Profile menu and select Developer.” — [S5] verified verbatim
↗ developer.calendly.com/docs/authentication/creating-an-oauth-appClick Create OAuth app. App name allows letters, numbers, hyphens and spaces only. Environment type = Sandbox. Enter a single redirect URI (http://localhost:PORT/callback is allowed in Sandbox).
“App name: use letters, numbers, hyphens, and spaces only.” — [S5] verified verbatim
Select the minimum scope set your agent needs — at least one is required. Agent can draft the justification list; you click the checkboxes.
“Select the scopes that your app needs. Select at least one scope.” — [S5] verified verbatim
Generate a CODE_VERIFIER, SHA-256 it to a CODE_CHALLENGE, then redirect the user's browser to the authorize URL with code_challenge_method=S256.
“Build a CODE_CHALLENGE from the verifier with SHA-256.” — [S5] verified verbatim
◆ prepared by agent · PKCE S256 helper (Node)import crypto from 'node:crypto'; // PKCE S256 — mandatory for every Calendly OAuth app export function pkce() { const verifier = crypto.randomBytes(32).toString('base64url'); const challenge = crypto.createHash('sha256').update(verifier).digest('base64url'); return { verifier, challenge }; } const { verifier, challenge } = pkce(); const url = new URL('https://auth.calendly.com/oauth/authorize'); url.searchParams.set('client_id', process.env.CALENDLY_CLIENT_ID); url.searchParams.set('response_type', 'code'); url.searchParams.set('redirect_uri', process.env.CALENDLY_REDIRECT_URI); url.searchParams.set('code_challenge_method', 'S256'); url.searchParams.set('code_challenge', challenge); // persist `verifier` server-side, keyed to the user's sessionPOST to https://auth.calendly.com/oauth/token with grant_type=authorization_code, code, the same redirect_uri, client_id and code_verifier. Server-side apps also send the client secret via HTTP Basic.
“Send a POST request to Get Access Token at https://auth.calendly.com/oauth/token. Include these parameters:” — [S5] verified verbatim
◆ prepared by agent · Token exchange (server-side)curl -X POST https://auth.calendly.com/oauth/token \ -u "$CALENDLY_CLIENT_ID:$CALENDLY_CLIENT_SECRET" \ -d grant_type=authorization_code \ -d code="$CODE" \ -d redirect_uri="$CALENDLY_REDIRECT_URI" \ -d client_id="$CALENDLY_CLIENT_ID" \ -d code_verifier="$CODE_VERIFIER"
Copy client ID, client secret and webhook signing key before leaving the creation screen — they are not viewable again. Then run a full consent + API call round trip in Sandbox.
“Copy all three values and store them securely before you leave this screen. You cannot view the client secret or the webhook signing key again.” — [S5] verified verbatim
Make it production-ready
Docs recommend a second app for Production rather than editing the sandbox one. Redirect URI must be https. Update your env vars and re-run the flow.
“Create a second app for Production when you are ready to use real customer data.” — [S5] verified verbatim
Read the FAQ page Calendly links to for the conditions that revoke an access token; wire refresh/reauth into the agent before going live. Page not in fetched sources, so no specifics here.
04Requirements, scopes & nuances
You'll need
- ▸A Calendly account (log in or sign up) to reach Developer tools. sourced ❝[S5]
- ▸Exactly one redirect URI per app, matching the environment rules (Sandbox: https or http on localhost; Production: https only). sourced ❝[S5]
- ▸At least one scope selected when creating the app. sourced ❝[S5]
- ▸PKCE verifier + SHA-256 challenge on every authorization request. sourced ❝[S5]
- ▸Secure storage for client secret and webhook signing key captured at creation time. sourced ❝[S5]
Gotchas
- !PKCE with S256 is mandatory for every Calendly OAuth app; an authorization request without a code challenge fails. sourced ❝[S5]
- !Each OAuth app has exactly one redirect URI — you cannot register a localhost URI and a production URI on the same app. sourced ❝[S5]
- !Environment rules differ: Sandbox accepts https URIs and http on localhost; Production accepts https only. sourced ❝[S5]
- !Client secret and webhook signing key are shown once at creation; the docs also state the client ID cannot be viewed again in Developer tools. sourced ❝[S5]
- !For server-side apps, the token exchange authenticates with HTTP Basic using client_id as username and client_secret as password. sourced ❝[S5]
- !The documented authorize host 301-redirects to calendly.com/oauth/authorize; anything that refuses redirects on the authorize step will break. tested[probe]
| Scope / permission | Tier | Note | Evidence |
|---|---|---|---|
| At least one scope (names not in the fetched source) | basic | Calendly requires a minimum of one scope at app creation and links to a separate Scopes reference page that was not fetched — pick the narrowest listed scope rather than guessing names here. | sourced ❝[S5] |
05If you get blocked
→ Manage OAuth apps at developer.calendly.com until your account finishes migrating, then retry the Profile menu.
→ Always send code_challenge plus code_challenge_method=S256 and the matching code_verifier at token exchange.
→ Keep a separate Production app with an https redirect, or edit the single URI (pencil icon) before switching environments.
→ Register a new OAuth app and store the new values immediately; treat the old app as disposable.
→ Let your HTTP client follow redirects on the authorize URL, or point the browser at https://calendly.com/oauth/authorize with the same query string.
06Evidence: what was tested, sourced, and still uncertain
Sources read
- [S1] Pass app review official
- [S2] Creating an OAuth app - GitHub Docs official
- [S3] Configure OAuth official
- [S4] App review process and requirements for the Google Workspace Marketplace official
- [S5] Creating an OAuth app official
- [S6] Klaviyo Developers official
- [S7] App approval guidelines official
- [composio] Composio — Managed OAuth apps directory official
- [probe] Live HTTP probes run by the agent (dummy client_id, no credentials) probe
Still uncertain
- ? Only one of the seven fetched sources (S5) is about Calendly; S1-S4, S6 and S7 cover Shopify, GitHub, Google, Klaviyo and Atlassian and were not used for any Calendly claim.
- ? Scope names are not in the fetched source — Calendly's Scopes reference page was not fetched, so read it before choosing scopes.
- ? No source states an approval or review gate for creating a Calendly OAuth app or acting on behalf of users; whether listing in any Calendly app directory/marketplace needs review is unknown and is not claimed.
- ? Token lifetimes, refresh-token rotation and revocation conditions live on pages that were not fetched.
- ? The probe only confirmed the authorize endpoint's 301 redirect; token endpoint behavior, error responses and scope enforcement were not tested.
- ? All durations are inferred estimates; the sources give no timings.
- ? Generated automatically; no app was registered and no review was submitted.