PTO Request Form Setup Guide

This guide covers everything you need to set up the PTO Request Form workflow end to end.


Copy the Google Form and Google Sheet

  1. Visit tl-hr.com and enter your license key to access the configurator
  2. Download your pre-configured workflow and copy the Google Form and Google Sheet templates provided
  3. Make copies of both into your Google Workspace account

Link the Copied Form to the Copied Sheet

  1. Open your copied Google Form
  2. Go to the Responses tab
  3. Click the Link to Sheets icon (looks like a spreadsheet with a link)
  4. Select Select existing spreadsheet
  5. Choose your copied Google Sheet from the list
  6. Click Link

Create/Setup Google Cloud Project (if not created yet)

Enable Gmail API (skip if already done)

  1. Go to console.cloud.google.com
  2. Select your project
  3. In the left sidebar, go to APIs & Services → Library
  4. Search for Gmail API
  5. Click on Gmail API in the results
  6. Click Enable

Enable Google Sheets API (skip if already done)

  1. Go to console.cloud.google.com
  2. Select your project
  3. In the left sidebar, go to APIs & Services → Library
  4. Search for Google Sheets API
  5. Click on Google Sheets API in the results
  6. Click Enable

Enable Google Calendar API (skip if already done)

  1. Go to console.cloud.google.com
  2. Select your project
  3. In the left sidebar, go to APIs & Services → Library
  4. Search for Google Calendar API
  5. Click on Google Calendar API in the results
  6. Click Enable

Enable Admin SDK API (skip if already done)

  1. Go to console.cloud.google.com
  2. Select your project
  3. In the left sidebar, go to APIs & Services → Library
  4. Search for Admin SDK API
  5. Click on Admin SDK API in the results
  6. Click Enable

Create OAuth Consent Screen (skip if already done)

  1. Go to APIs & Services → OAuth consent screen
  2. Choose Internal (since this is for internal use)
  3. Click Create
  4. Fill in the required fields:
    • App name (e.g. "n8n")
    • User support email — select your email from the dropdown
    • Developer contact email — enter your email
  5. Click Save and Continue
  6. On the Scopes step, click Save and Continue — you can skip adding scopes here since n8n handles this automatically
  7. Click Back to Dashboard

Create OAuth Client (skip if already done)

  1. Go to console.cloud.google.com
  2. Select your project
  3. Go to APIs & Services → Credentials
  4. Click Create credentials → OAuth client ID
  5. Application type → Web application
  6. Name the OAuth client (e.g. "n8n")
  7. Authorized redirect URIs → https://your-n8n.com/rest/oauth2-credential/callback
  8. Click Create
  9. Copy Client ID and Client Secret

Note: You will only see the client secret once, so make sure to copy and/or download the JSON.


Set Up the Shared Google Calendar

The workflow needs a shared Google Calendar to check for conflicts and add approved PTO events.

Create a Shared Calendar

  1. Go to calendar.google.com
  2. In the left sidebar under Other calendars, click the + button
  3. Select Create new calendar
  4. Give it a name (e.g. "PTO Calendar" or "Time Off")
  5. Optionally add a description (e.g. "Shared PTO and time-off calendar")
  6. Click Create calendar

Find the Calendar ID

You can get the Calendar ID in two ways — the configurator accepts either format:

Option 1: Copy from Integrate calendar (recommended)

  1. In the left sidebar, hover over your new calendar
  2. Click the three dots (⋮) that appear
  3. Select Settings and sharing
  4. Scroll down to the Integrate calendar section
  5. Copy the Calendar ID — it looks like c_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b@group.calendar.google.com

Option 2: Paste the share link

  1. In the left sidebar, hover over your new calendar
  2. Click the three dots (⋮) that appear
  3. Select Settings and sharing
  4. In the Get shareable link section, click Get shareable link
  5. Copy the entire link (it will be base64-encoded — the configurator decodes it automatically)

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.


Enable the Google Calendar API (skip if already done)

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.

  1. Go to console.cloud.google.com
  2. Select your project
  3. Go to APIs & Services → Library
  4. Search for Google Calendar API
  5. Click Google Calendar API
  6. Click Enable
  7. Wait 1-2 minutes for the change to propagate

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.


Create the Service Account (skip if already done)

  1. Go to console.cloud.google.com
  2. Select your project
  3. Go to APIs & Services → Credentials
  4. Click Create Credentials → Service Account
  5. Give it a name (e.g. "n8n-service-account")
  6. Copy the service account email address (e.g. n8n-service-account@project-name.iam.gserviceaccount.com)
  7. Click Create and Continue — skip the optional role and user access steps
  8. Click Done

Warning: New Google Workspace organizations have the following org policies enforced by default which will block service account and key creation:

  • iam.managed.disableServiceAccountCreation
  • iam.disableServiceAccountKeyCreation
  • iam.managed.disableServiceAccountKeyCreation

Before creating your service account key, you must temporarily unenforce these policies:

  1. Go to console.cloud.google.com
  2. In the top search bar, search for Organization Policies
  3. 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
  4. For each of the three policies listed above, click on it, select Override parent's policy, set to Not enforced, and save

Create a JSON Key (skip if already done)

  1. Click on your newly created service account
  2. Go to the Keys tab
  3. Click Add Key → Create new key
  4. Choose JSON and click Create
  5. The key file will download automatically
  6. Open n8n and import the key immediately (covered in the Connect Credentials section below)
  7. Delete the JSON file from your Downloads folder after importing
  8. If you need to keep a backup, store it somewhere secure — not your Desktop, not email, and not a shared drive

Enable Domain-Wide Delegation (skip if already done)

  1. Go to the Details tab of your service account
  2. Click the Advanced settings tab
  3. Note the Client ID shown — you will need this in the next step

Authorize in Google Workspace Admin Console

  1. Go to admin.google.com

  2. Go to Security → Access and data control → API controls

  3. Scroll down and click Manage Domain Wide Delegation

  4. Find your Service Account's existing entry in the list and click Edit. If no entry exists yet, click Add new instead.

  5. Paste in the Service Account Client ID (if adding new) or confirm it matches (if editing)

  6. 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.

  7. Click Authorize

Note: Domain Wide Delegation can take up to 24 hours to propagate but in my experience it updates fairly immediately.


Re-enforce Organization Policies (skip if already done)

Once your service account credential is confirmed working in n8n, re-enforce the three org policies to secure your Google Workspace:

  1. Go to console.cloud.google.com

  2. In the top search bar, search for Organization Policies

  3. For each of the three policies below, click on it, select Override parent's policy, set to Enforced, and save:

    • iam.managed.disableServiceAccountCreation
    • iam.disableServiceAccountKeyCreation
    • iam.managed.disableServiceAccountKeyCreation

This ensures your organization is protected against unauthorized service account and key creation going forward.


Connect Credentials in n8n

Create the Gmail Credential (skip if already done)

  1. Open your n8n instance
  2. Click Overview in the left sidebar
  3. Click Credentials
  4. Click Create credential in the top right
  5. Search and select Gmail OAuth2 API
  6. Paste your Client ID and Client Secret from the OAuth client step
  7. Click Sign in with Google
  8. A browser window will open. Sign in with the Google Workspace admin account
  9. Grant the requested permissions
  10. You will be redirected back to n8n. The credential will show as connected

Create the Google Sheets Credential (skip if already done)

  1. Open your n8n instance
  2. Click Overview in the left sidebar
  3. Click Credentials
  4. Click Create credential in the top right
  5. Search and select Google Sheets OAuth2 API
  6. Paste your Client ID and Client Secret from the OAuth client step
  7. Click Sign in with Google
  8. A browser window will open. Sign in with the Google Workspace admin account
  9. Grant the requested permissions
  10. You will be redirected back to n8n. The credential will show as connected

Create the Google Service Account Credential (skip if already done)

  1. Open your n8n instance
  2. Click Overview in the left sidebar
  3. Click Credentials
  4. Click Create credential in the top right
  5. Search and select Google Service Account API
  6. Select the region closest to you (this does not matter)
  7. Open the downloaded JSON key file. Find the Service Account Email (client_email) and paste it into the Service Account Email field
  8. From the downloaded JSON, find the Private Key (private_key) and paste the full value into the private key field (everything between and including -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY-----\n)
  9. Toggle Impersonate a User on and enter your email (the Google Workspace admin)
  10. Toggle Set up for use in HTTP Request node on
  11. Add the scope: https://www.googleapis.com/auth/calendar.events
  12. Set Allowed HTTP Request Domains to Specific Domains and enter admin.googleapis.com,www.googleapis.com
  13. When all fields are complete, you should see Connection tested successfully

The PTO workflow calls both the Admin SDK Directory API (admin.googleapis.com) and the Google Calendar API (www.googleapis.com). If you omit www.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.

Required n8n credential settings for the PTO workflow

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:

  1. Open your n8n instance
  2. Click Overview in the left sidebar
  3. Click Credentials
  4. Find Google Service Account API in the list and click on it
  5. Verify the Service Account Email field is filled in
  6. Verify the Private Key field is filled in (starts with -----BEGIN PRIVATE KEY-----)
  7. Verify Impersonate a User is toggled on, and the impersonated user is your Google Workspace admin email
  8. Toggle Set up for use in HTTP Request node to on — this is required for the credential to work with HTTP Request nodes
  9. In the Scope field, add https://www.googleapis.com/auth/calendar.events
  10. Under Allowed HTTP Request Domains, select Specific Domains and enter admin.googleapis.com,www.googleapis.com
  11. Click Save
  12. Click Connection test — it should report success

If any of these four settings is wrong:

Common errors when setting up the Google Service Account

unauthorized_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:

  1. The n8n Service Account credential has https://www.googleapis.com/auth/calendar.events in its Scope field (per the Required n8n credential settings section above)
  2. The Google Workspace Admin Console has the calendar scope in the Service Account's DWD entry (per the DWD step in this guide)

If both are set, propagation may be the cause — DWD changes can take up to a few hours to take effect.


Find your Credential IDs in n8n (skip if already done)

Each credential you create in n8n has a unique ID. You need these IDs to configure your workflow.

  1. Open your n8n instance
  2. Click Credentials in the left sidebar
  3. Find the credential you need and click on it to open it
  4. Go to the Details tab
  5. Copy the ID field

You need three credential IDs (no separate Calendar credential required — the Service Account handles Calendar API access via HTTP Request):


Understand the Approval Flow

The PTO Request Form workflow uses a two-step approval process:

  1. 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.

  2. Manager approves or rejects — The email sent to the manager contains two links:

    • Approvehttps://your-n8n.com/webhook/pto-request-decision?action=approve&email=employee@example.com
    • Rejecthttps://your-n8n.com/webhook/pto-request-decision?action=reject&email=employee@example.com

    Both links point to the same webhook URL at the pto-request-decision path. The action parameter tells the workflow which decision was made.

  3. Workflow processes the decision

    • Approved: The workflow creates a calendar event on the shared PTO calendar, sends a confirmation email to the employee, and updates the Sheet row to Approved with a decision timestamp.
    • Rejected: The workflow sends a notification email to the employee and updates the Sheet row to Rejected with a decision timestamp.

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.


Configure PTO Request Form Workflow

  1. Go to https://tl-hr.com/configure/pto-request-form-google-workspace
  2. Enter the passcode (included in your purchase receipt)
  3. Fill in the form:
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
  1. Click Download Workflow JSON to download the configured workflow
  2. Click Download Apps Script to download the configured Google Apps Script file

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.


Import the Apps Script into the Sheet

  1. Open your copied Google Sheet
  2. Click Extensions → Apps Script
  3. In the new window, the Code.gs file should be empty
  4. Open the downloaded pto-request-form-google-workspace-appscript.gs file in a text editor
  5. Copy and paste the entire contents into the empty Code.gs file
  6. Select setup in the function dropdown and click the Run button
  7. Approve the permissions when prompted
  8. You will see Execution started and then Execution completed in the log
  9. Close the Apps Script editor

Import the Workflow into n8n

  1. Create a new workflow in n8n
  2. Click the kebab menu button (three dots) on the top right
  3. Select Import from file
  4. Select the downloaded pto-request-form-google-workspace-configured.json file
  5. Click Save to save the workflow
  6. Click Publish to set the workflow live

Test the Workflow

1. Submit a PTO Request

  1. Open your Google Form and submit a test PTO request using your own email and manager's email

2. Verify the Initial Submission

  1. Open your Google Sheet and check the PTO Records tab
  2. Verify a new row was created with status Pending
  3. Check that all fields are populated correctly

3. Verify the Manager Receives the Approval Email

  1. Check the manager's email inbox (or your own if you used the same address)
  2. Verify the email contains:
    • The employee's name and details
    • An Approve link with action=approve in the URL
    • A Reject link with action=reject in the URL

4. Test the Approved Path

  1. Click the Approve link in the email
  2. You should see a confirmation page saying "Approved!"
  3. Verify the following happened:
    • A calendar event was created on the shared PTO calendar
    • The employee received a confirmation email
    • The Sheet row updated to Approved with a decision timestamp

5. Test the Rejected Path

  1. Submit another PTO request through the form
  2. Click the Reject link in the email
  3. You should see a confirmation page saying "Declined"
  4. Verify the following happened:
    • The employee received a rejection notification email
    • The Sheet row updated to Rejected with a decision timestamp

6. Verify Error Handling

  1. Intentionally submit a form with missing required fields (e.g. leave the email blank)
  2. Verify the error is logged in the Error Log tab
  3. Verify the alert email is sent to the configured alert address