Appearance
Google Sheets node
IMPORTANT
This node is an installable component. It never sees your service-account key, or the access token that key buys: it writes a placeholder where the credential goes, and FlowRunner signs the JWT, exchanges it, and substitutes the real token as the request leaves.
The Google Sheets node appends a row to a spreadsheet or reads a range from it, mid-flow — a spreadsheet-as-a-database for logging submissions, appending leads, or pulling a lookup table.
Component id: flowrunner/sheets.
How it works
The node authenticates as a Google service account (server-to-server — no login pop-up, no stored OAuth connection), then calls the Sheets API. You provide:
- the service account JSON, as a secret reference (
${secrets.GOOGLE_SERVICE_ACCOUNT}) so the private key never lives in the flow; - an operation — append a row, or read a range;
- the spreadsheet ID (the long token in the sheet's URL) — may be a flow reference;
- a range in A1 notation (
Sheet1!A:C); - for append, the row cells, one per line: each is a flow reference (
start.name) whose value is used, or a literal.
The result is stored under your result variable:
text
# append →
refs.<resultVar> = { updatedRange: "Sheet1!A5:C5" }
# read →
refs.<resultVar> = { values: [ ["a","b"], ["1","2"] ] }Appends use valueInputOption=USER_ENTERED, so dates and numbers are interpreted the same way as if a person had typed them. As a safeguard, a string cell that begins with a formula trigger (=, +, -, @) is stored as plain text — untrusted form or webhook input can't become a live formula (a spreadsheet-injection attack). Real numbers are unaffected.
One-time setup
- In the Google Cloud console, create a service account and download its JSON key.
- Enable the Google Sheets API for the project.
- Share the spreadsheet with the service account's
client_email(it appears in the JSON) — Editor access to append, Viewer to read. - Paste the whole JSON into a workspace secret named
GOOGLE_SERVICE_ACCOUNT.
Safety
- The service account JSON is a credential — it resolves from
${secrets.*}/${env.*}only, never from flow input, so a form visitor can't swap it. - Row cells that arrive as strings beginning with
=,+,-, or@are stored as text, so untrusted input can't become an executable formula. - The node does not auto-retry — a failed append isn't safe to replay blindly (it could double-write). Wire the error port to handle failures.
Config
| Field | Required | Description |
|---|---|---|
serviceAccount | Yes | Service account JSON, as a secret reference. |
operation | No (default append) | append a row, or read a range. |
spreadsheetId | Yes | The spreadsheet's ID (from its URL). May be a flow reference. |
range | Yes | A1 notation — Sheet1!A:C to append, Sheet1!A1:C10 to read. |
values | append only | Row cells, one per line — a flow reference (value used) or a literal. |
resultVar | No (default sheet) | The variable the result is written to. |
Ports
next and error.
Examples
Log every form submission as a new row:
text
Sheets serviceAccount: ${secrets.GOOGLE_SERVICE_ACCOUNT}
operation: append
spreadsheetId: 1A2b3C4d5E...
range: "Leads!A:C"
values:
start.name
start.email
start.message
resultVar: logged
# → refs.logged.updatedRange = "Leads!A42:C42"Read a lookup table into the flow:
text
Sheets operation: read
spreadsheetId: ${start.sheetId}
range: "Prices!A2:B"
resultVar: prices
# → refs.prices.values = [ ["basic","10"], ["pro","30"] ]TIP
Store the service account JSON once under Secrets as GOOGLE_SERVICE_ACCOUNT, and remember to share the sheet with its client_email — a "Requested entity was not found" error almost always means the sheet wasn't shared.