# Google Calendar Integration with Service Account ## Overview Using a Service Account to integrate Google Calendar API without OAuth user consent. ## Setup Instructions ### 1. Create Service Account in Google Cloud Console 1. Go to [Google Cloud Console](https://console.cloud.google.com/) 2. Create a new project or select existing one 3. Navigate to **IAM & Admin** → **Service Accounts** 4. Click **Create Service Account** 5. Fill in details: - Name: `access-hub-calendar` - Description: `Service account for Access Hub calendar integration` 6. Click **Create and Continue** 7. Skip granting roles (not needed for Calendar API) 8. Click **Done** ### 2. Enable Google Calendar API 1. In Google Cloud Console, go to **APIs & Services** → **Library** 2. Search for "Google Calendar API" 3. Click on it and press **Enable** ### 3. Create Service Account Key 1. Go to your service account page 2. Click on the **Keys** tab 3. Click **Add Key** → **Create New Key** 4. Select **JSON** format 5. Click **Create** - this will download a JSON file with credentials 6. **Keep this file secure** - it contains your private key The JSON file looks like: ```json { "type": "service_account", "project_id": "your-project-id", "private_key_id": "...", "private_key": "-----BEGIN PRIVATE KEY-----\n...", "client_email": "access-hub-calendar@your-project-id.iam.gserviceaccount.com", "client_id": "...", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token" } ``` ### 4. Share Calendar with Service Account 1. Go to [Google Calendar](https://calendar.google.com/) 2. Find the calendar you want to use (e.g., your main calendar) 3. Click the **three dots** next to the calendar name 4. Select **Settings and sharing** 5. Scroll to **Share with specific people** 6. Click **+ Add people** 7. Enter the service account email: `access-hub-calendar@your-project-id.iam.gserviceaccount.com` 8. Set permissions to **Editor** (can make changes to events) 9. Click **Send** (ignore the email notification) ### 5. Get Calendar ID - For your primary calendar: `your-email@gmail.com` - For other calendars: Go to Calendar Settings → **Integrate calendar** → **Calendar ID** ## n8n Workflow Configuration ### Option A: Using Google Calendar Node 1. Add a **Google Calendar** node to your workflow 2. Select **Service Account** as authentication 3. Paste the entire Service Account JSON content 4. Select the calendar ID 5. Choose operation: **Create Event** ### Option B: Using HTTP Request Node (More Control) ```javascript // In n8n Code node or HTTP Request node const { GoogleToken } = require('gtoken'); const { google } = require('googleapis'); // Service account credentials const serviceAccount = { type: 'service_account', project_id: 'your-project-id', private_key_id: '...', private_key: '-----BEGIN PRIVATE KEY-----\n...', client_email: 'access-hub-calendar@your-project-id.iam.gserviceaccount.com', client_id: '...', }; // Create JWT client const jwtClient = new google.auth.JWT( serviceAccount.client_email, null, serviceAccount.private_key, ['https://www.googleapis.com/auth/calendar'] ); // Authorize and create event jwtClient.authorize(async (err, tokens) => { if (err) { console.error('JWT authorization error:', err); return; } const calendar = google.calendar({ version: 'v3', auth: jwtClient }); const event = { summary: 'Konsultasi: ' + $json.topic + ' - ' + $json.client_name, start: { dateTime: new Date($json.date + 'T' + $json.start_time).toISOString(), timeZone: 'Asia/Jakarta', }, end: { dateTime: new Date($json.date + 'T' + $json.end_time).toISOString(), timeZone: 'Asia/Jakarta', }, description: 'Client: ' + $json.client_email + '\n\n' + $json.notes, attendees: [ { email: $json.client_email }, ], conferenceData: { createRequest: { requestId: $json.slot_id, conferenceSolutionKey: { type: 'hangoutsMeet' }, }, }, }; try { const result = await calendar.events.insert({ calendarId: $json.calendar_id, resource: event, conferenceDataVersion: 1, }); return { meet_link: result.data.hangoutLink, event_id: result.data.id, }; } catch (error) { console.error('Error creating calendar event:', error); throw error; } }); ``` ## Incoming Webhook Payload Your n8n webhook at `/webhook-test/create-meet` will receive: ```json { "slot_id": "uuid-of-slot", "date": "2025-12-25", "start_time": "14:00:00", "end_time": "15:00:00", "client_name": "John Doe", "client_email": "john@example.com", "topic": "Business Consulting", "notes": "Discuss project roadmap", "calendar_id": "your-calendar@gmail.com", "brand_name": "Your Brand", "test_mode": true } ``` ## Expected Response Your n8n workflow should return: ```json { "meet_link": "https://meet.google.com/abc-defg-hij", "event_id": "event-id-from-google-calendar" } ``` ## Security Notes 1. **Never commit the service account JSON** to version control 2. Store it securely in n8n credentials 3. Rotate the key if compromised 4. Only grant minimum necessary permissions to the service account ## Troubleshooting ### Error: 403 Forbidden - Check if the calendar is shared with the service account email - Verify the service account has **Editor** permissions ### Error: 401 Unauthorized - Verify the service account JSON is correct - Check if Calendar API is enabled in Google Cloud Console ### Error: 400 Invalid - Check date/time format (should be ISO 8601) - Verify calendar ID is correct - Ensure the service account email format is correct ## Alternative: Use Google Calendar API Key (Less Secure) If you don't want to use service accounts, you can create an API key: 1. Go to Google Cloud Console → **APIs & Services** → **Credentials** 2. Click **Create Credentials** → **API Key** 3. Restrict the key to Google Calendar API only 4. Use it with HTTP requests However, this is **not recommended** for production as it's less secure than service accounts.