This guide covers everything you need to set up the PTO Request Form workflow end to end.
https://your-n8n.com/rest/oauth2-credential/callbackNote: You will only see the client secret once, so make sure to copy and/or download the JSON.
The workflow needs a shared Google Calendar to check for conflicts and add approved PTO events.
You can get the Calendar ID in two ways — the configurator accepts either format:
Option 1: Copy from Integrate calendar (recommended)
c_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b@group.calendar.google.comOption 2: Paste the share link
Important: The shared calendar must be owned by (or shared with) the Google Workspace admin account that the Service Account impersonates, with Make changes to events permission. This allows the Service Account to create events on the calendar via domain-wide delegation. No separate Google Calendar OAuth2 credential is needed — the workflow uses the HTTP Request node with the Service Account to call the Calendar API directly.
To share: go to the calendar's Settings and sharing, under Share with specific people, add the Service Account impersonated user's email with Make changes to events permission.
You'll need this Calendar ID when configuring the workflow.
The Google Calendar API must be enabled in your Google Cloud project before the Service Account can use it. The Admin SDK Directory API (used by onboarding and offboarding) is enabled by default, but the Calendar API is not.
If you skip this step, the Create Calendar Event node will fail with:
Google Calendar API has not been used in project [PROJECT_ID] before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/calendar-json.googleapis.com/overview?project=[PROJECT_ID] then retry.
n8n-service-account@project-name.iam.gserviceaccount.com)Warning: New Google Workspace organizations have the following org policies enforced by default which will block service account and key creation:
iam.managed.disableServiceAccountCreationiam.disableServiceAccountKeyCreationiam.managed.disableServiceAccountKeyCreationBefore creating your service account key, you must temporarily unenforce these policies:
- Go to console.cloud.google.com
- In the top search bar, search for Organization Policies
- Note: The console only shows 50 policies at a time by default — scroll past the first 50 or search by name to find each policy
- For each of the three policies listed above, click on it, select Override parent's policy, set to Not enforced, and save
Go to admin.google.com
Go to Security → Access and data control → API controls
Scroll down and click Manage Domain Wide Delegation
Find your Service Account's existing entry in the list and click Edit. If no entry exists yet, click Add new instead.
Paste in the Service Account Client ID (if adding new) or confirm it matches (if editing)
In the OAuth scopes field, add the following scopes (if editing, append to any existing scopes):
https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/calendar,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/userinfo.profile,openid,https://www.googleapis.com/auth/documents,https://www.googleapis.com/auth/spreadsheets,https://www.googleapis.com/auth/admin.chrome.printers,https://mail.google.com/,https://www.googleapis.com/auth/drive.appdata,https://www.googleapis.com/auth/drive.photos.readonly,https://www.googleapis.com/auth/drive.file,https://www.googleapis.com/auth/drive.metadata,https://www.googleapis.com/auth/gmail.labels,https://www.googleapis.com/auth/gmail.addons.current.action.compose,https://www.googleapis.com/auth/gmail.addons.current.message.action,https://www.googleapis.com/auth/gmail.modify,https://www.googleapis.com/auth/gmail.compose,https://www.googleapis.com/auth/admin.directory.user
n8n validates all Domain-Wide Delegation scopes when authenticating, not just the ones your workflow uses. If any scope is missing the entire authentication fails. Make sure the full scope list is added exactly as shown above in the Google Workspace Admin Console under Security → Access and data control → API controls → Manage Domain Wide Delegation. No extra spaces, no missing scopes.
Click Authorize
Note: Domain Wide Delegation can take up to 24 hours to propagate but in my experience it updates fairly immediately.
Once your service account credential is confirmed working in n8n, re-enforce the three org policies to secure your Google Workspace:
Go to console.cloud.google.com
In the top search bar, search for Organization Policies
For each of the three policies below, click on it, select Override parent's policy, set to Enforced, and save:
iam.managed.disableServiceAccountCreationiam.disableServiceAccountKeyCreationiam.managed.disableServiceAccountKeyCreationThis ensures your organization is protected against unauthorized service account and key creation going forward.
client_email) and paste it into the Service Account Email fieldprivate_key) and paste the full value into the private key field (everything between and including -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY-----\n)https://www.googleapis.com/auth/calendar.eventsadmin.googleapis.com,www.googleapis.comThe PTO workflow calls both the Admin SDK Directory API (
admin.googleapis.com) and the Google Calendar API (www.googleapis.com). If you omitwww.googleapis.com, the Create Calendar Event node will fail with:Domain not allowed: This credential is restricted from accessing https://www.googleapis.com/calendar/v3/... Only the following domains are allowed: admin.googleapis.com.
The Service Account credential in n8n must have the following four settings configured correctly, otherwise the Create Calendar Event node will fail with Forbidden - perhaps check your credentials? / Request had insufficient authentication scopes.
To check or edit these on an existing credential:
-----BEGIN PRIVATE KEY-----)https://www.googleapis.com/auth/calendar.eventsadmin.googleapis.com,www.googleapis.comIf any of these four settings is wrong:
calendar.events → Google rejects the Calendar API call with insufficient scopeswww.googleapis.com → HTTP Request nodes are blocked from calling the Calendar API even with a valid scopeadmin.googleapis.com → HTTP Request nodes are blocked from calling the Admin SDK Directory APIunauthorized_client
n8n validates all Domain-Wide Delegation scopes when authenticating, not just the ones your workflow uses. If any scope is missing the entire authentication fails. Make sure the full scope list is added exactly as shown in the Google Workspace Admin Console under Security → Access and data control & API controls → Manage Domain Wide Delegation. No extra spaces, no missing scopes.
invalid_grant (Private key validation failed)
This is usually a propagation delay. After setting up or updating Domain-Wide Delegation in the Admin Console, it can take up to a few hours to take effect. If you see this error immediately after setup, wait a few hours and try again before troubleshooting further.
HTTP Request Domain blocked
The "Set up for use in HTTP Request node" toggle on the Google Service Account credential in n8n must be turned on, and the Allowed HTTP Request Domains must be set to Specific Domains with admin.googleapis.com,www.googleapis.com. If the Calendar API calls fail, double-check that www.googleapis.com is included in addition to admin.googleapis.com.
Forbidden - Request had insufficient authentication scopes
The Calendar API rejected the request because the OAuth token does not include the calendar scope. Two things must both be true:
https://www.googleapis.com/auth/calendar.events in its Scope field (per the Required n8n credential settings section above)If both are set, propagation may be the cause — DWD changes can take up to a few hours to take effect.
Each credential you create in n8n has a unique ID. You need these IDs to configure your workflow.
You need three credential IDs (no separate Calendar credential required — the Service Account handles Calendar API access via HTTP Request):
The PTO Request Form workflow uses a two-step approval process:
Employee submits form — The Google Form submission triggers the Apps Script, which sends the data to the n8n webhook. The workflow creates a record in the Google Sheet with status Pending and sends an email to the manager.
Manager approves or rejects — The email sent to the manager contains two links:
https://your-n8n.com/webhook/pto-request-decision?action=approve&email=employee@example.comhttps://your-n8n.com/webhook/pto-request-decision?action=reject&email=employee@example.comBoth links point to the same webhook URL at the pto-request-decision path. The action parameter tells the workflow which decision was made.
Workflow processes the decision —
Both paths (form submission and decision) are handled by a single workflow using two webhook triggers. The forms webhook (pto-request-form) receives submissions from the Apps Script, and the decision webhook (pto-request-decision) receives approval or rejection clicks.
https://tl-hr.com/configure/pto-request-form-google-workspace| Field | Description |
|---|---|
| Company name | Your company name |
| Google Workspace domain | e.g. acme.com |
| Gmail credential ID | The ID from the Gmail credential in n8n |
| Google Sheets credential ID | The ID from the Sheets credential in n8n |
| Google Service Account credential ID | The ID from the Service Account credential in n8n |
| n8n webhook URL (base) | e.g. https://your-n8n-instance.com/webhook/pto-request-form — the form webhook path |
| Shared Calendar ID | The Calendar ID from your shared PTO calendar — looks like c_abcdef123456@group.calendar.google.com |
| Google Sheets ID | The ID from your Google Sheet URL (the long string in https://docs.google.com/spreadsheets/d/THIS-ID/edit) |
| Alert email | Email to receive error messages if the workflow fails |
Important: The Apps Script is installed on the Google Sheet (not the Form). Unlike other templates where the script goes on the Form, the PTO script uses a Sheet-based trigger that fires when a new form response row is added. This allows it to pass the row number to the workflow so the workflow can update the correct row when the manager approves or rejects.
Code.gs file should be emptypto-request-form-google-workspace-appscript.gs file in a text editorCode.gs filesetup in the function dropdown and click the Run buttonpto-request-form-google-workspace-configured.json fileaction=approve in the URLaction=reject in the URL