This guide walks you through setting up Cal.com Atoms in your application using OAuth authentication.
1. Create an OAuth client
First, create an OAuth client to enable user authentication:
- Go to https://app.cal.com/settings/developer/oauth
- Create a new OAuth client with:
- Name: Your application name
- Redirect URIs: URLs where users are redirected after authorization (e.g.,
https://yourapp.com/callback)
Your OAuth client will be reviewed by Cal.com. Once approved, you can use it to authenticate users.
See the OAuth documentation for complete details.
2. Install the atoms package
3. Implement the OAuth flow
When a user wants to connect their Cal.com account:
- Redirect to authorization URL
const authUrl = `https://app.cal.com/auth/oauth2/authorize?client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&state=${STATE}`;
window.location.href = authUrl;
- Handle the callback
After authorization, the user is redirected to your callback URL with a code parameter.
- Exchange code for tokens
const response = await fetch("https://api.cal.com/v2/auth/oauth2/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
grant_type: "authorization_code",
code: authorizationCode,
redirect_uri: REDIRECT_URI,
}),
});
const { access_token, refresh_token, expires_in } = await response.json();
// Store these tokens securely
4. Set up a token refresh endpoint
Access tokens expire after 30 minutes. Create an endpoint that atoms can call to refresh tokens:
// pages/api/refresh.js (Next.js example)
export default async function handler(req, res) {
const expiredToken = req.headers.authorization?.replace("Bearer ", "");
// Look up the refresh token for this user in your database
const refreshToken = await getRefreshTokenForUser(expiredToken);
const response = await fetch("https://api.cal.com/v2/auth/oauth2/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
client_id: process.env.CAL_OAUTH_CLIENT_ID,
client_secret: process.env.CAL_OAUTH_CLIENT_SECRET,
grant_type: "refresh_token",
refresh_token: refreshToken,
}),
});
const tokens = await response.json();
// Store the new tokens in your database
await updateTokensForUser(expiredToken, tokens);
res.json({ accessToken: tokens.access_token });
}
For atoms to work, the root of your application must be wrapped with CalOAuthProvider. This provider handles authentication and token management for all atoms in your app.
See the CalOAuthProvider documentation for all available props and advanced configuration.
import "@calcom/atoms/globals.min.css";
import { CalOAuthProvider } from "@calcom/atoms";
function MyApp({ Component, pageProps }) {
const { user } = useAuth(); // Your auth context
return (
<CalOAuthProvider
accessToken={user?.calAccessToken}
clientId={process.env.NEXT_PUBLIC_CAL_OAUTH_CLIENT_ID}
options={{
apiUrl: "https://api.cal.com/v2",
refreshUrl: "/api/refresh",
}}
>
<Component {...pageProps} />
</CalOAuthProvider>
);
}
export default MyApp;
For all provider properties see Cal OAuth Provider docs.
6. Start using atoms
Now you can use any atom in your components:
import { Booker, AvailabilitySettings } from "@calcom/atoms";
export default function SchedulingPage() {
return (
<div>
<h1>Book a meeting</h1>
<Booker
username="johndoe"
eventSlug="30min"
/>
<h2>Manage availability</h2>
<AvailabilitySettings />
</div>
);
}