FlowKit

Automating Google Docs with n8n: generate documents on the fly

Published 4 August 2026 · 6 min read

Meeting minutes, sales proposals, simple contracts, creative briefs, generated documentation: a large share of the documents a team produces follow the same skeleton, where only the client name, the dates, and a few paragraphs change. Writing them by hand means copy-pasting the latest one and leaving an occurrence of the previous client's name in the middle of page 3. With n8n, the Google Docs + Google Drive duo turns this chore into a pipeline: a trigger event, a duplicated template, replaced placeholders, a PDF sent out. This guide covers the native node and its limits, the robust template method with replaceAllText, AI-generated content, and the final PDF export.

Prerequisite: the Google OAuth2 credential

The Google Docs node authenticates via OAuth2, exactly like its Sheets and Drive cousins. The full walkthrough — Google Cloud project, consent screen, OAuth client, redirect URL — is detailed in our guide to setting up Google OAuth2 in n8n. Two Docs-specific points:

  • enable the Google Docs API in the Google Cloud project (on top of the Drive API, which you'll need for the template method);
  • the required scope is https://www.googleapis.com/auth/documents — if the credential was created before the API was enabled, reconnect it, or you'll harvest 403 "insufficient authentication scopes" errors.

As always in production: a Google account dedicated to automation, with access only to the folders involved.

The native Google Docs node: simple but limited

The Google Docs node covers three operations:

  • Create: creates a blank document, with a title and a destination Drive folder. Handy for generating a dated meeting note in the right place ("Meeting notes — {{date}}" in the project folder).
  • Get: retrieves a document's content — useful for proofreading a generated document or feeding a downstream process.
  • Update: inserts text into the document, via an Insert text action.

And that's where the limit shows: insertion is plain text only. No bold, no structured headings, no tables, no logo — the native node doesn't drive the Docs API's rich formatting. For a throwaway internal note, that's enough. For a sales proposal going to a client with your brand guidelines, it's a deal-breaker. Hence the method that follows, the one every serious document pipeline uses.

The robust method: duplicate a template and replace placeholders

The principle: the formatting lives in a Google Docs template created once by hand (headings, styles, logo, pricing table, legal footer), and the workflow only touches the text. In the template, every variable value becomes a placeholder: {{client}}, {{date}}, {{amount}}, {{subject}}.

Trigger (form, Sheets, CRM)
        │
        ▼
Google Drive — Copy          (duplicates the template, names the copy)
        │
        ▼
HTTP Request — batchUpdate   (replaceAllText on each placeholder)
        │
        ▼
Google Drive — Download      (PDF export)
        │
        ▼
Gmail — Send                 (delivery to the recipient)

Step 1 — duplicate the template. The Google Drive node, Copy operation, takes the template's ID and creates a copy in the target folder, with a name built from the data ("Proposal — Acme — 2026-08-04"). The node's output contains the copy's ID: that's what you work with from then on, never the original. The Drive node's other operations are detailed in our Google Drive guide for n8n.

Step 2 — replace the placeholders. The native Google Docs node doesn't offer text replacement, but the Docs API does it very well via batchUpdate and its replaceAllText request. An HTTP Request node in POST, authenticated with the same Google OAuth2 credential (Predefined Credential Type option → Google Docs), pointed at:

POST https://docs.googleapis.com/v1/documents/{{ $json.id }}:batchUpdate

with the following JSON body:

{
  "requests": [
    {
      "replaceAllText": {
        "containsText": { "text": "{{client}}", "matchCase": true },
        "replaceText": "Acme LLC"
      }
    },
    {
      "replaceAllText": {
        "containsText": { "text": "{{date}}", "matchCase": true },
        "replaceText": "August 4, 2026"
      }
    },
    {
      "replaceAllText": {
        "containsText": { "text": "{{amount}}", "matchCase": true },
        "replaceText": "$4,800"
      }
    }
  ]
}

A single call replaces every placeholder, throughout the document, while preserving the template's formatting: if {{amount}} was bold inside a table, "$4,800" comes out bold inside the table. In practice, you build the replaceText values with n8n expressions ({{ $json.client_name }}) from the trigger's data or an upstream node.

Generating the content with AI upstream

For documents where entire sections vary — a proposal's context, a meeting summary, a brief's specific clauses — a Basic LLM Chain placed before the batchUpdate writes the text to inject. The pattern: the prompt receives the raw data (meeting notes, CRM fields, form answers) and produces each section in a dedicated field, which replaceAllText inserts into its placeholder ({{context}}, {{summary}}).

This isn't just a convenience gain: a study by Shakked Noy and Whitney Zhang published in Science in 2023 ("Experimental evidence on the productivity effects of generative artificial intelligence"), run as a controlled experiment on professional writing tasks, shows that LLM assistance substantially reduces writing time while improving the average quality of the documents produced. The n8n pipeline takes the logic one step further: the AI writes the variable sections, the template guarantees the structure and the branding, and the human only reviews what matters.

Still, keep a review step for binding documents (proposals, contracts): a {{status}} placeholder set to "DRAFT" in the template, removed manually after sign-off, is a simple and effective guardrail.

PDF export and delivery

A Google Doc travels poorly outside the Google ecosystem; the final deliverable is almost always a PDF. The Google Drive node's Download operation, pointed at the copy's ID, offers export conversion for Google-native formats: pick application/pdf and the PDF binary lands in the workflow. All that's left is to send it as an attachment with the Gmail node — setup is covered in our Gmail guide for n8n — or archive it in the client's folder.

For numbered documents like quotes and invoices, where numbering and totals follow their own rules, our guide on generating PDF quotes and invoices with n8n details a dedicated pipeline.

Typical triggers

  • Form: a multi-step n8n form that collects a prospect's needs and triggers the sales proposal within the minute.
  • New Google Sheets row: an opportunities spreadsheet where each "to send" row generates its document — the trigger and its subtleties are covered in our Google Sheets guide for n8n.
  • CRM: a webhook when a deal moves to the "proposal" stage (HubSpot, Pipedrive…), with the deal's fields as input data.
  • Scheduled: a weekly report generated every Friday from the week's data.

Common errors

  • Insufficient OAuth scopes. The 403 "insufficient authentication scopes" error almost always means the Docs API wasn't enabled when the credential was created, or the token predates it. Enable the API, reconnect the credential, run again.
  • API quota. The Docs API enforces per-minute, per-project request limits. batchUpdate helps a lot — one request for all the placeholders rather than one call per placeholder — but a massive catch-up job (regenerating 500 documents in a tight loop) will end in 429 errors: process in batches.
  • Placeholders not replaced. Three classic causes: a placeholder typed in several passes in the template that Google split into internal "runs" (retype it in one go), mismatched spaces ({{ client }}{{client}}), or a matchCase that doesn't forgive letter case. Robustness tip: at the end of the workflow, run a Get on the document and check that no {{ remains — if any does, notify instead of sending.
  • Editing the original instead of the copy. If your replacements target the template's ID rather than the copy's, the template is destroyed on the first run. Lock the template's ID in a dedicated variable and only pass the Copy node's output to batchUpdate.

Going further

A document that generates itself means the end of risky copy-paste and proposals that go out with the wrong client's name. The Drive template + replaceAllText + PDF export trio is the core building block; plug a form, a Sheets row, or a CRM upstream, an AI for the written sections, and Gmail downstream — and the team's document production becomes a flow, not a chore.

FAQ

Frequently asked questions

Can you format text (bold, headings, tables) with n8n's Google Docs node?

Not directly: the native node's Update operation inserts plain text, with no rich formatting. The right approach is to start from a pre-formatted Google Docs template (headings, logo, tables, styles) and only replace text placeholders like {{client}} or {{amount}} via the batchUpdate API's replaceAllText request, called with an HTTP Request node. The template's formatting is preserved; only the text changes.

Why aren't my {{client}} placeholders being replaced in the document?

The most common cause: the placeholder in the document doesn't exactly match the string sent in replaceAllText. Google Docs can split a placeholder into several invisible 'runs' if it was typed in multiple passes or corrected — retype it in one go in the template. Also check for spaces ({{ client }} is not {{client}}), letter case if matchCase is on, and make sure you're targeting the template's copy, not the original.

How do I convert a Google Doc to PDF with n8n?

Use the Google Drive node's Download operation on the document's ID: for Google-native formats, it offers on-the-fly export conversion. Pick application/pdf as the format and n8n receives the PDF binary, ready to send as a Gmail attachment, archive in a Drive folder, or push to a CRM.

Which OAuth scope do you need to work with Google Docs from n8n?

The Google Docs API requires the https://www.googleapis.com/auth/documents scope (and the Docs API enabled in the Google Cloud project). Since the template method also goes through Drive (copying the template, exporting to PDF), the Drive scope is needed in practice. If you get a 403 'insufficient authentication scopes' error, reconnect the credential after enabling the APIs and checking the scopes: the existing token won't update itself.

Bundle FlowKit Complet

€269