Overview
Checks whether a specific user has connected their Google Calendar to your platform. Useful before attempting to schedule meetings.
Authentication
Requires Platform API Key in the X-API-Key header.
Request
GET https://api.syncline.run/v1/platform/users/status?email=alice@example.com
Query Parameters
Email address of the user to check
Response
User Connected
{
"connected": true,
"user_email": "alice@example.com",
"google_id": "103847562910384756291",
"connected_at": "2025-01-15T10:30:00Z",
"timezone": "America/New_York",
"preferences": {
"work_hours": {
"monday": { "enabled": true, "start": "09:00", "end": "17:00" }
},
"buffer_minutes": 15,
"energy_pattern": "morning_person"
},
"calendar_access": "read_write"
}
User Not Connected
{
"connected": false,
"user_email": "alice@example.com",
"message": "User has not connected their calendar"
}
Response Fields
Whether the user has connected their calendar
The email address that was checked
Google account ID (only if connected)
ISO 8601 timestamp of when they connected (only if connected)
User’s scheduling preferences (only if connected)
Use Cases
Pre-Flight Check Before Scheduling
async function scheduleWithCheck(attendees, meetingDetails) {
// Check all attendees are connected
for (const email of attendees) {
const status = await checkUserStatus(email);
if (!status.connected) {
// Get OAuth URL for this user
const { oauth_url } = await getOAuthURL(email);
return {
error: 'user_not_connected',
user_email: email,
message: `${email} needs to connect their calendar`,
oauth_url
};
}
}
// All connected - proceed with scheduling
return await scheduleMeeting(attendees, meetingDetails);
}
Conditional UI Rendering
// React component
function ScheduleMeetingButton({ attendeeEmail }) {
const [status, setStatus] = useState(null);
useEffect(() => {
checkStatus(attendeeEmail).then(setStatus);
}, [attendeeEmail]);
if (!status) return <LoadingSpinner />;
if (!status.connected) {
return (
<button onClick={() => window.open(status.oauth_url)}>
Connect Calendar First →
</button>
);
}
return (
<button onClick={scheduleMeeting}>
Schedule Meeting ✓
</button>
);
}
Batch Connection Status
// Check multiple users at once
async function checkMultipleUsers(emails) {
const checks = await Promise.all(
emails.map(email => checkUserStatus(email))
);
const connected = checks.filter(c => c.connected);
const notConnected = checks.filter(c => !c.connected);
return {
all_connected: notConnected.length === 0,
connected_count: connected.length,
not_connected_users: notConnected.map(c => c.user_email)
};
}
// Usage
const status = await checkMultipleUsers([
'alice@example.com',
'bob@example.com',
'charlie@example.com'
]);
if (!status.all_connected) {
console.log('These users need to connect:');
status.not_connected_users.forEach(email => {
console.log(`- ${email}`);
});
}
Connection Health Monitoring
// Check connection health for all your users
async function auditConnections() {
const { users } = await getAllUsers();
const statuses = await Promise.all(
users.map(u => checkUserStatus(u.email))
);
const stats = {
total: users.length,
connected: statuses.filter(s => s.connected).length,
not_connected: statuses.filter(s => !s.connected).length,
connection_rate: 0
};
stats.connection_rate = (stats.connected / stats.total * 100).toFixed(1);
return stats;
}
// Run daily
const stats = await auditConnections();
console.log(`Connection Rate: ${stats.connection_rate}%`);
console.log(`Connected: ${stats.connected}/${stats.total} users`);
Error Responses
Invalid Email
{
"error": "Invalid email format",
"message": "Please provide a valid email address"
}
Missing Email Parameter
{
"error": "Email parameter required",
"message": "Please provide an email query parameter"
}
Best Practices
Cache Connection Status
// Cache status for 5 minutes to avoid repeated API calls
const connectionCache = new Map();
async function checkUserStatusCached(email) {
const cached = connectionCache.get(email);
if (cached && Date.now() - cached.timestamp < 5 * 60 * 1000) {
return cached.status;
}
const status = await checkUserStatus(email);
connectionCache.set(email, {
status,
timestamp: Date.now()
});
return status;
}
Handle Disconnections Gracefully
async function scheduleOrPromptConnection(attendees, details) {
const checks = await Promise.all(
attendees.map(email => checkUserStatus(email))
);
const notConnected = checks.filter(c => !c.connected);
if (notConnected.length > 0) {
// Don't fail silently - prompt users to connect
const oauthUrls = await Promise.all(
notConnected.map(c => getOAuthURL(c.user_email))
);
return {
success: false,
needs_connection: notConnected.map((c, i) => ({
email: c.user_email,
oauth_url: oauthUrls[i].oauth_url
})),
message: 'Some users need to connect their calendars'
};
}
// All connected - schedule
return await scheduleMeeting(attendees, details);
}
Proactive Notification
// Notify users when their connection expires
async function notifyDisconnectedUsers() {
const { users } = await getAllUsers();
for (const user of users) {
const status = await checkUserStatus(user.email);
if (!status.connected && user.was_previously_connected) {
// Send email notification
await sendEmail({
to: user.email,
subject: 'Reconnect your calendar',
body: `Your calendar connection has expired. Reconnect here: ${oauth_url}`
});
}
}
}