Call the /v1/platform/oauth-url endpoint with your secret key (sk_live_xxx) to get a pre-built URL.
GET https://api.syncline.run/v1/platform/oauth-url?user_email=alice@example.comAuthorization: Bearer sk_live_xyz789...
Response:
{ "oauth_url": "https://api.syncline.run/v1/auth/google/authorize?platform_key=pk_live_abc...&user_email=alice@example.com", "instructions": "Redirect your user to this URL to connect their Google Calendar"}
// Publishable key (safe for URLs) - from your dashboardconst PUBLISHABLE_KEY = 'pk_live_abc123...'// Secret key (server-side only) - from your dashboardconst SECRET_KEY = 'sk_live_xyz789...'// Build OAuth URL (no API call needed)function sendCalendarInvite(userEmail) { const oauthUrl = `https://api.syncline.run/v1/auth/google/authorize?` + `platform_key=${PUBLISHABLE_KEY}` + `&user_email=${encodeURIComponent(userEmail)}` + `&redirect_uri=${encodeURIComponent('https://myapp.com/callback')}` + `&state=${encodeURIComponent(userEmail)}` // Send to user via email, chat, SMS, etc. sendMessage(userEmail, `Connect your calendar: ${oauthUrl}`)}
Always use the state parameter to prevent CSRF attacks:
const state = crypto.randomBytes(32).toString('hex');// Store state in session/databasereq.session.oauthState = state;// Include in OAuth URLconst { oauth_url } = await getOAuthURL(userEmail, state);// Verify on callbackapp.get('/oauth/callback', (req, res) => { const { state } = req.query; if (state !== req.session.oauthState) { return res.status(400).send('Invalid state parameter'); } // Process callback...});